Часы и термометр своими руками с помощью arduino, ds1307, 8-ми сдвиговых регистров и 4 светодиодных матриц 8х8

Датчик температуры и влажности (DHT11) висит в серверной, и выведен по витой паре
Здесь коротенькое видео:

Код для ардуины

Download file _4matrix8x8_w8shiftreg2_alphabet.ino
#include <Wire.h>
#include <dht11.h>
#include "RTClib.h"
 
RTC_DS1307 RTC;
 
dht11 DHT11;
 
#define DHT11PIN 2
 
const byte clockPin = 7; //
const byte latchPin = 8; //  номера выходов ардуины для записи чисел в регистры
const byte dataPin =  9; //
 
const byte NumRegs = 8;  // количество сдвиговых регистров
const byte NumMatrix = 4;// количество матриц 8х8
const byte NumCols=8;
const byte NumRows=8;
 
byte n[NumMatrix];
 
byte Col_bits[NumMatrix][NumCols] = {{ 4,62,61, 7,59, 6, 2, 1},
                                     {12,54,53,15,51,14,10, 9},
                                     {20,46,45,23,43,22,18,17},
                                     {28,38,37,31,35,30,26,25}};   
        // вот в этом массиве я указал соотношение колонок
        // к номеру выхода регистров, т.е. 1-я колонка 1-й матрицы
        // светодиодов припаяна к 4-му выходу регистров и т.д. 
        // у каждой следующей матрицы такая же колонка имеет номер регистра либо +8  либо -8 ;)
 
byte Row_bits[NumMatrix][NumRows] = {{ 8, 3,57, 5,64,58,63,60},
                                     {16,11,49,13,56,50,55,52},
                                     {24,19,41,21,48,42,47,44},
                                     {32,27,33,29,40,34,39,36}}; 
        // в этом массиве перечислены номера
        // выходов регистров отвечающих за строки
byte Regs[NumRegs];
byte reg_n, bit_n, in_r, in_c;   //вспомогательные переменные, массивы. 
                                //Главное чтоб размер данных не был больше 2кбайт! ;)
 
boolean flag = true;
 
//здесь массив с аscii изображениями букв побитно. Вот возьмем например цифру 8 из массива, 
//                     {B00000000,B00011100,B00100010,B00100010,B00011100,B00100010,B00100010,B00011100}, // 8
//вобьем на каждой строчке по бинарной цифре
//B00000000
//B00011100
//B00100010
//B00100010
//B00011100
//B00100010
//B00100010
//B00011100
// теперь уберем B и вместо 0 поставим пробелы
//       
//   111
//  1   1
//  1   1
//   111
//  1   1
//  1   1
//   111
// ничего не напоминает? ;)
 
byte number[16][8]={ {B00000000,B00011100,B00100010,B00100010,B00100010,B00100010,B00100010,B00011100}, // 0
                     {B00000000,B00001000,B00011000,B00101000,B00001000,B00001000,B00001000,B00111110}, // 1
                     {B00000000,B00011100,B00100010,B00000010,B00000100,B00001000,B00010000,B00111110}, // 2
                     {B00000000,B00011100,B00100010,B00000010,B00001100,B00000010,B00100010,B00011100}, // 3
                     {B00000000,B00000100,B00001100,B00010100,B00100100,B00111110,B00000100,B00000100}, // 4
                     {B00000000,B00111110,B00100000,B00111100,B00000010,B00000010,B00100010,B00011100}, // 5
                     {B00000000,B00011100,B00100010,B00100000,B00111100,B00100010,B00100010,B00011100}, // 6
                     {B00000000,B00111110,B00000010,B00000100,B00001000,B00001000,B00001000,B00001000}, // 7
                     {B00000000,B00011100,B00100010,B00100010,B00011100,B00100010,B00100010,B00011100}, // 8
                     {B00000000,B00011100,B00100010,B00100010,B00011110,B00000010,B00100010,B00011100}, // 9
                     {B01100000,B10010000,B10010110,B01101001,B00001000,B00001000,B00001001,B00000110}, // 10 = °C  
                     {B01100000,B10010010,B10010100,B01101000,B00010110,B00101001,B01001001,B00000110}, // 11 = % 
                     {B00000000,B01000000,B01000000,B01000000,B11100000,B01000000,B01001000,B00110000}, // 12 = t+ 
                     {B00000000,B00000000,B01000000,B01000000,B11100111,B01000000,B01001000,B00110000}, // 13 = t-
                     {B00000100,B00111100,B01001010,B01001010,B01010010,B01010010,B00111100,B00100000}, // 14 = ɸ
                     {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000}  // 15 = empty  
};
 
 
 
void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
 
  Wire.begin();
  RTC.begin();
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}
 
void loop() {
 
  for(int k = 0; k<11; k++ )
  {
    for(int i = 0; i<28; i++ )
    {
      DateTime now = RTC.now();
      n[0] = now.hour() / 10;
      n[1] = now.hour() % 10;
      n[2] = now.minute() / 10;
      n[3] = now.minute() % 10;
      burn_matrix();
    }
    flag = ! flag;
  }
  flag = false;
 
  //DHT11.humidity,
  int chk = DHT11.read(DHT11PIN);
  if(DHT11.temperature >= 0)
  {
    n[0] = 12;
  }
  else
  {
    n[0] = 13;
  }
  n[1] = DHT11.temperature  / 10;
  if(n[1]==0) n[1] = 15;
  n[2] = DHT11.temperature  % 10;
  n[3] = 10; 
 
  for(int k = 0; k<200; k++ )
  {
      burn_matrix();
  }
  n[0] = 14;
  n[1] = DHT11.humidity  / 10;
  if(n[1]==0) n[1] = 15;
  n[2] = DHT11.humidity  % 10;
  n[3] = 11; 
  for(int k = 0; k<200; k++ )
  {
      burn_matrix();
  }
 
}
 
void burn_matrix()      
{    // функция для поджигания светодиодов - зажигает 1-ю колонку, гасит ее, 
     // поджигает 2-ю колонку, гасит ее и так далее до 10-й колонки
 
  for(int c = 0; c < NumCols; c++)
  {
    for(int i = 0; i < NumRegs; i++)
    {
      Regs[i]=255;
    }
 
    for(int m = 0; m < NumMatrix; m++)
    {
      reg_n = (Col_bits[m][c]-1) / 8;
      bit_n = (Col_bits[m][c]-1) % 8;
      bitWrite(Regs[reg_n], bit_n, 0);
 
      for(int r = 0; r < NumRows; r++)
      {
        reg_n = (Row_bits[m][r]-1) / 8;
        bit_n = (Row_bits[m][r]-1) % 8;
        bitWrite(Regs[reg_n], bit_n, bitRead(number[n[m]][r], 7-c));
      }
    }
 
    if(flag)
    {// manual draw of pulsing points
      if(c==0)
      {
        reg_n = (Row_bits[2][3]-1) / 8;
        bit_n = (Row_bits[2][3]-1) % 8;
        bitWrite(Regs[reg_n], bit_n, 1);
        reg_n = (Row_bits[2][5]-1) / 8;
        bit_n = (Row_bits[2][5]-1) % 8;
        bitWrite(Regs[reg_n], bit_n, 1);
      }
    }
//    delayMicroseconds(50);    
    registerWrite();
  }
}
 
void registerWrite() 
{
  digitalWrite(latchPin, LOW);
  for(int cur_reg = NumRegs-1; cur_reg >= 0; cur_reg-- )
  {
    shiftOut(dataPin, clockPin, MSBFIRST, Regs[cur_reg]);
  }
  digitalWrite(latchPin, HIGH);
}
 
 
 
 
//Celsius to Fahrenheit conversion
double Fahrenheit(double celsius)
{
	return 1.8 * celsius + 32;
}
 
//Celsius to Kelvin conversion
double Kelvin(double celsius)
{
	return celsius + 273.15;
}
 
// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm 
double dewPoint(double celsius, double humidity)
{
	double A0= 373.15/(273.15 + celsius);
	double SUM = -7.90298 * (A0-1);
	SUM += 5.02808 * log10(A0);
	SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
	SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
	SUM += log10(1013.246);
	double VP = pow(10, SUM-3) * humidity;
	double T = log(VP/0.61078);   // temp var
	return (241.88 * T) / (17.558-T);
}
 
// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
	double a = 17.271;
	double b = 237.7;
	double temp = (a * celsius) / (b + celsius) + log(humidity/100);
	double Td = (b * temp) / (a - temp);
	return Td;
}