Страница 1 из 1

MSMDClock_displey

Добавлено: 22 дек 2019, 19:03
Sergey2055
Всем привет. Ниже будет представлен проект (в набросках, проект совсем сырой и требует детальной проработки и оптимизации) дисплея для умного дома для вывода разной информации, такой как температура, влажность, время, дата итд. в данных набросках реализован прямой вывод информации. От бегущей строки я отказался слишком давит на мозг. В данном скетче реализованы: получение и вывод уличной температуры, влажности, время пока устанавливается ручками. В планах автоматизировать время, регулировку яркости в зависимости от показаний люксометра, ну и возможно вывод еще какой то информации. Пока набросан такой алгоритм: 40 секунд показывается время и по 10 температура и влажность. После каждой минуты меняется цвет дисплея. Дисплей построен на адресных диодах WS2812.

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

#define MY_DEBUG
#define MY_NODE_ID AUTO
#define MY_PARENT_NODE_ID AUTO
#define MY_RADIO_RF24
#define MY_RF24_PA_LEVEL RF24_PA_MAX

#include <MySensors.h>
#include <avr/wdt.h>
#include <EEPROM.h>

#define SKETCH_NAME "MSMDClock_displey"
#define SKETCH_MAJOR_VER "1"
#define SKETCH_MINOR_VER "0"


#define SID_TIME          1
#define SID_TEMP          2
#define SID_HUM           3
#define SID_DATE          4
#define SID_MSMD          210
#define SID_NodeID        211
#define SID_FREQ          212
#define SID_PARENT_SELECT 213

#define MaxByte  0xFF
#define MaxWord  0xFFFF

#define mFreq     8

#define cGateAdr 0
#define DEF_FREQUENCY 1 // min
#define DEB_SWITCH_PIN  3
#define MAXTRY 5 //Количество попыток отправки пакета.
#define PAUSETX 100

unsigned long Freq = DEF_FREQUENCY*60*1000ul, oldFreq = 0;

void(* resetFunc) (void) = 0;

#include "FastLED.h"  //Подключаем библиотеку FastLED
#define NUM_LEDS 300  //Определяем количество светодиодов на табло
#define DATA_PIN 5   //Пин, по которому происходит управление табло
#define ROWS 10        //Количество строк табло
#define COLS 30       //Количество столбцов табло
#define minRGB 2      //Минимальная яркость светодиодов в обычном режиме работы
#define colorOrder GRB//Порядок цветов для FastLED
#include "fonts.h"


#define C_BLACK 0x000000
#define C_GREEN 0x00FF00
#define C_RED 0xFF0000
#define C_BLUE 0x0000FF
#define C_PURPLE 0xFF00FF
#define C_YELLOW 0xFFFF00
#define C_CYAN 0x00FFFF
#define C_WHITE 0xFFFFFF

unsigned long color  =  C_WHITE, color2, oldinterval2, time1, mil;

CRGB leds[NUM_LEDS]; //Массив светодиодов для работы с FastLED
int c,br,a=0,n=0,xStep, interval2 = 1000, Temp, Hum, year, month, day, Time_minute, Time_hour;  //Служебные переменные
boolean flag=true, flag1, ig=true,ib=true,selfPowered,qt,first=true,dimmed;  //Служебные переменные
char ch;  //Переменная для хранения полученного из буфера последовательного порта символа
byte  clrs[4];  //Т.к. цвет часов в автономном режиме плавно изменяется, яркости его каналов (красного, зелёного и синего) хранятся в этом массиве
byte maxRGB[4];//Массив с макисмальными яркостями для каждого из каналов в автономном режиме (ограничивается, чтобы потребляемый ток табло не превысил ток, выдаваемый источником питания)
unsigned long syncTime,syncedTime=00000000, Time, time,timeX; //Переменные для реализации алгоритма работы часов
unsigned long k60=60000; //Количество миллисекунд в минуте - коэффициент для отладки.
byte Hour_high, Houl_low, Min_high, Min_low, h, m, s, T1, flag2;

//Функция зажигает светодиод n цветом r,g,b (выключенный светодиод n это частный случай зажигания светодиода n цветом 0,0,0)
void setLed(int n,byte r,byte g,byte b) {
    //n = n+ COLS;
    leds[n].r=r;
    leds[n].g=g;
    leds[n].b=b;
}
 void clear_displey (){
     for (int m=0; m<NUM_LEDS; m++) {
          leds[m].r = 0;
          leds[m].g = 0;
          leds[m].b = 0;}
          FastLED.show();  //Синхронизируем табло с массивом leds (обновляем информацию на нём в соответствии с содержимым массива)
}

//Функция выводит текущее время в массив светодиодов leds[], используя вышеописанные функции PutDigit и putDots.
void putTime() {
  if(flag2 == 1) {clear_displey ();}

                conversion_text(4,1,(Min_low)+48,color);
                conversion_text(3,1,(Min_high)+48,color);
                conversion_text(2,1,':',color2);
                conversion_text(1,1,(Houl_low)+48,color);
                conversion_text(0,1,(Hour_high)+48 ,color);

               // putDots(r,g,b);
}

MyMessage msgTime(SID_TIME, V_TEXT);
MyMessage msgTemp(SID_TEMP, V_TEMP);
MyMessage msgHum(SID_HUM,   V_HUM);
MyMessage msgDate(SID_DATE,   V_TEXT);
MyMessage msgFreq(SID_FREQ, V_VAR1);

 // String  var = getValue( StringVar, ',', 2); // if  a,4,D,r  would return D        
String getValue(String data, char separator, int index){
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length();

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
        return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}  // END

void before(){  
  wdt_disable();

  pinMode(DEB_SWITCH_PIN, INPUT_PULLUP);  
  if (digitalRead(DEB_SWITCH_PIN) == LOW){    
    
    for (int i=0;i<512;i++)
      EEPROM.write(i, 0xFF);   
  }


  //=== Read from memory
  // Freq
  uint8_t fBVal = loadState(mFreq);
  if (fBVal != MaxByte) {    
    Freq = int(fBVal)*60*1000ul;
  }
  
}    

void presentation() { 
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);
  
  present(SID_TIME,   S_INFO,    "Text_time");
  wait(300);
  present(SID_TEMP,   S_TEMP,    "Temp");
  wait(300);  
  present(SID_HUM,    S_HUM,     "HUM");
  wait(300);    
  present(SID_DATE,   S_INFO,    "Date_text");
  wait(300);    
  present(SID_MSMD,   S_CUSTOM, "a00678cb4bc49c5e");
  wait(300);
  present(SID_NodeID, S_CUSTOM, "Node ID");
  wait(300);
  present(SID_FREQ,   S_CUSTOM, "NODE FREQ MINUTE");
  wait(300);
  present(SID_PARENT_SELECT, S_CUSTOM, "NODE_PARENT_SELECT");
} 

void setup() {
  wdt_enable(WDTO_8S);
    FastLED.addLeds<WS2812B, DATA_PIN, colorOrder>(leds, NUM_LEDS); //Инициализируем библиотеку FastLED с заданными нами параметрами. Теперь массив leds - это данные о всех наших пикселях на табло.
    clear_displey ();
    FastLED.setBrightness(255); //Устанавливаем максимально возможную яркость (диапазон для каждого канала 0-255)
   // request_data();  
    requestTime();
    Serial.print ("Time ");
    Serial.println (time1);
    wait(2000);

}

void loop (){      wdt_reset();

                    FastLED.setBrightness(30); //Устанавливаем яркость на максимум, чтобы эти значения соответствовали себе (иначе FastLED их пропорционально затемнит)

  
//ПП обработки часов
  if (millis() - mil > 1000 || first){
      mil = millis();
  //    T1++;
      if(flag2 == 0) flag2 = 1;
      s++;
      first=false; //Всё, уже не впервые
      if(s == 60) {s = 0; m++; xStep++; color_new(xStep);}
      if(m == 60) {m = 0; h++;}
      if(h == 24) {h = 0;}
      if(s < 40){
        timeget();
        flag2 = 2;
      flag1 = !flag1;
      if(flag1 == 1){color2 = color;} else {color2 = C_BLACK;}
      }
      else if(s < 50) { tempget(); flag2 = 3;}    
             else if(s < 60) { humget(); flag2 = 1;} 
      
   }
 
}


void receive(const MyMessage &message) {

  if (message.isAck()) {
    return;
  }
 
  String Str = ""; bool z;
  uint8_t Dest = message.sender;

  // Request
  if (mGetCommand(message) == C_REQ) {

    switch (message.sensor) {

    case SID_FREQ:
        send( msgFreq.set(Freq / (60*1000)) );
       break;
    }
    return;
  }

  // Set NULL date (if empty sensors)
  if (strlen(message.getString()) == 0) {
    return;
  }

  switch (message.sensor) {
    
  case SID_TIME:
      m = word(getValue(String(message.getString()), ',', 0).toInt()); //выделяется нулевой элемент строки и приводится к типу инт и потом в ворд
      h = word(getValue(String(message.getString()), ',', 1).toInt()); //выделяется первый элемент строки и приводится к типу инт и потом в ворд
      timeget ();
    break;   

  case SID_TEMP:
    Temp = message.getInt();  
    break;  

  case SID_HUM:
    Hum = message.getInt();  
    break;  

  case SID_DATE:
      year = word(getValue(String(message.getString()), ',', 0).toInt()); //выделяется нулевой элемент строки и приводится к типу инт и потом в ворд
      month = word(getValue(String(message.getString()), ',', 1).toInt()); //выделяется первый элемент строки и приводится к типу инт и потом в ворд 
      day = word(getValue(String(message.getString()), ',', 2).toInt()); //выделяется первый элемент строки и приводится к типу инт и потом в ворд 
    break;         
  
  case SID_FREQ:
    Freq = message.getByte() * 60*1000ul;
    saveState(mFreq, message.getByte());    
    break;

  // NODE_NEW_ID; type == V_VAR1
  case SID_NodeID:
    byte Node_ID = message.getByte();
      hwWriteConfig(EEPROM_NODE_ID_ADDRESS, Node_ID);
      resetFunc();
      break;

    // NODE_NEW_PARENT; type == V_VAR1
  case SID_PARENT_SELECT:
    byte Node_Parent = message.getByte();
      hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, Node_Parent);
      resetFunc();
      break;
  }  
}

void tempget (){
 if(flag2 == 2) {clear_displey ();}
char b[3];
String str;
str=String(Temp);
str.toCharArray(b,3);
if(str[2] == 0){
   if(str[1] == 0){
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,('~'),color);
      conversion_text(3,1,('C'),color);      
   }
   else
   {  
      conversion_text(0,1,(str[0]),color);
      conversion_text(1,1,(str[1]),color);
      conversion_text(2,1,('~'),color);
      conversion_text(3,1,('C'),color);      
   }
}
else {
      conversion_text(0,1,(str[0]),color);
      conversion_text(1,1,(str[1]),color);
      conversion_text(2,1,(str[2]),color);
      conversion_text(3,1,('~'),color);
      conversion_text(4,1,('C'),color);
}
FastLED.show(); //Синхронизируем табло с массивом leds
}
void humget () {
 if(flag2 == 3) {clear_displey ();}
char b[3];
String str;
str=String(Hum);
str.toCharArray(b,3);
if(str[2] == 0){
   if(str[1] == 0){
      conversion_text(2,1,(str[0]),color);
      conversion_text(3,1,('%'),color);      
   }
   else
   {  
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,(str[1]),color);
      conversion_text(3,1,('%'),color);      
   }
}
else {
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,(str[1]),color);
      conversion_text(3,1,(str[2]),color);
      conversion_text(4,1,('%'),color);

}
FastLED.show(); //Синхронизируем табло с массивом leds
}

void request_data (){
    request(SID_TEMP, V_TEMP);
    wait(1000, SID_TEMP, V_TEMP);
    request(SID_HUM, V_HUM);
    wait(1000, SID_HUM, V_HUM);

}

void timeget () {
      Hour_high = h / 10;
      Houl_low = h % 10;
      Min_high = m % 60 / 10;
      Min_low = m % 10;
      putTime();
      FastLED.show(); //Синхронизируем табло с массивом leds
}

//функция смены цвета
void color_new(int i){
  switch (i) {
    case 1:
      color  = C_WHITE;
      break;
    case 2:
      color  = C_GREEN;
      break;
    case 3:
      color  = C_RED;
      break;
    case 4:
      color  = C_BLUE;
      break;
    case 5:
      color  = C_PURPLE;
      break;
    case 6:
      color  = C_YELLOW;
      break;
    case 7:
      color  = C_CYAN;
      break;   
  }
}


void conversion_text(int column, int line, byte text_type, unsigned long color_text){
  byte a; 
  byte r, g, b;
for (int i = 0; i<5; i++){
  a = 0; 
  a = read_text((byte)text_type, i);
  for(int k = 0; k < 7; k++){
    bool s = 0;
    s = bitRead(a,0);
    if(s == 1){r = color_text >> 16; g = color_text >> 8; b = color_text;} 
      else {r = 0; g = 0; b = 0;}
        if(column < COLS) {setLed((column*6+i+(k*COLS)+(line*COLS)),r,g,b);} 
        a = a >> 1;
  }
 }
}

uint8_t read_text (uint8_t font, uint8_t row){ 
  font = font - '0' + 16;   // перевод код символа из таблицы ASCII в номер согласно нумерации массива
  if (font <= 90) return pgm_read_byte(&(fontHEX[font][row]));     // для английских букв и символов
     else if (font >= 112 && font <= 159) {return pgm_read_byte(&(fontHEX[font - 17][row]));}     // для русских
              else if (font >= 96 && font <= 111) {return pgm_read_byte(&(fontHEX[font + 47][row]));}
                   else{return pgm_read_byte(&(fontHEX[font][row]));}
}

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

//FastLED.h
// шрифты для вывода текста
const uint8_t fontHEX[][5] PROGMEM = {
	{0x00, 0x00, 0x00, 0x00, 0x00}, //   0x20 32
	{0x00, 0x00, 0x6f, 0x00, 0x00}, // ! 0x21 33
	{0x00, 0x07, 0x00, 0x07, 0x00}, // " 0x22 34
	{0x14, 0x7f, 0x14, 0x7f, 0x14}, // # 0x23 35
	{0x00, 0x07, 0x04, 0x1e, 0x00}, // $ 0x24 36
	{0x23, 0x13, 0x08, 0x64, 0x62}, // % 0x25 37
	{0x36, 0x49, 0x56, 0x20, 0x50}, // & 0x26 38
	{0x00, 0x00, 0x07, 0x00, 0x00}, // ' 0x27 39
	{0x00, 0x1c, 0x22, 0x41, 0x00}, // ( 0x28 40
	{0x00, 0x41, 0x22, 0x1c, 0x00}, // ) 0x29 41
	{0x14, 0x08, 0x3e, 0x08, 0x14}, // * 0x2a 42
	{0x08, 0x08, 0x3e, 0x08, 0x08}, // + 0x2b 43
	{0x00, 0x50, 0x30, 0x00, 0x00}, // , 0x2c 44
	{0x08, 0x08, 0x08, 0x08, 0x08}, // - 0x2d 45
	{0x00, 0x60, 0x60, 0x00, 0x00}, // . 0x2e 46
	{0x20, 0x10, 0x08, 0x04, 0x02}, // / 0x2f 47
	{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 0x30 48
	{0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 0x31 49
	{0x42, 0x61, 0x51, 0x49, 0x46}, // 2 0x32 50
	{0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 0x33 51
	{0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 0x34 52
	{0x27, 0x45, 0x45, 0x45, 0x39}, // 5 0x35 53
	{0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 0x36 54
	{0x01, 0x71, 0x09, 0x05, 0x03}, // 7 0x37 55
	{0x36, 0x49, 0x49, 0x49, 0x36}, // 8 0x38 56
	{0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 0x39 57
	{0x00, 0x36, 0x36, 0x00, 0x00}, // : 0x3a 58
	{0x00, 0x56, 0x36, 0x00, 0x00}, // ; 0x3b 59
	{0x08, 0x14, 0x22, 0x41, 0x00}, // < 0x3c 60
	{0x14, 0x14, 0x14, 0x14, 0x14}, // = 0x3d 61
	{0x00, 0x41, 0x22, 0x14, 0x08}, // > 0x3e 62
	{0x02, 0x01, 0x51, 0x09, 0x06}, // ? 0x3f 63
	{0x3e, 0x41, 0x5d, 0x49, 0x4e}, // @ 0x40 64
	{0x7e, 0x09, 0x09, 0x09, 0x7e}, // A 0x41 65
	{0x7f, 0x49, 0x49, 0x49, 0x36}, // B 0x42 66
	{0x3e, 0x41, 0x41, 0x41, 0x22}, // C 0x43 67
	{0x7f, 0x41, 0x41, 0x41, 0x3e}, // D 0x44 68
	{0x7f, 0x49, 0x49, 0x49, 0x41}, // E 0x45 69
	{0x7f, 0x09, 0x09, 0x09, 0x01}, // F 0x46 70
	{0x3e, 0x41, 0x49, 0x49, 0x7a}, // G 0x47 71
	{0x7f, 0x08, 0x08, 0x08, 0x7f}, // H 0x48 72
	{0x00, 0x41, 0x7f, 0x41, 0x00}, // I 0x49 73
	{0x20, 0x40, 0x41, 0x3f, 0x01}, // J 0x4a 74
	{0x7f, 0x08, 0x14, 0x22, 0x41}, // K 0x4b 75
	{0x7f, 0x40, 0x40, 0x40, 0x40}, // L 0x4c 76
	{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M 0x4d 77
	{0x7f, 0x04, 0x08, 0x10, 0x7f}, // N 0x4e 78
	{0x3e, 0x41, 0x41, 0x41, 0x3e}, // O 0x4f 79
	{0x7f, 0x09, 0x09, 0x09, 0x06}, // P 0x50 80
	{0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q 0x51 81
	{0x7f, 0x09, 0x19, 0x29, 0x46}, // R 0x52 82
	{0x46, 0x49, 0x49, 0x49, 0x31}, // S 0x53 83
	{0x01, 0x01, 0x7f, 0x01, 0x01}, // T 0x54 84
	{0x3f, 0x40, 0x40, 0x40, 0x3f}, // U 0x55 85
	{0x0f, 0x30, 0x40, 0x30, 0x0f}, // V 0x56 86
	{0x3f, 0x40, 0x30, 0x40, 0x3f}, // W 0x57 87
	{0x63, 0x14, 0x08, 0x14, 0x63}, // X 0x58 88
	{0x07, 0x08, 0x70, 0x08, 0x07}, // Y 0x59 89
	{0x61, 0x51, 0x49, 0x45, 0x43}, // Z 0x5a 90
	{0x3c, 0x4a, 0x49, 0x29, 0x1e}, // [ 0x5b 91
	{0x02, 0x04, 0x08, 0x10, 0x20}, // \ 0x5c 92
	{0x00, 0x41, 0x7f, 0x00, 0x00}, // ] 0x5d 93
	{0x04, 0x02, 0x01, 0x02, 0x04}, // ^ 0x5e 94
	{0x40, 0x40, 0x40, 0x40, 0x40}, // _ 0x5f 95
	{0x00, 0x00, 0x03, 0x04, 0x00}, // ` 0x60 96
	{0x20, 0x54, 0x54, 0x54, 0x78}, // a 0x61 97
	{0x7f, 0x48, 0x44, 0x44, 0x38}, // b 0x62 98
	{0x38, 0x44, 0x44, 0x44, 0x20}, // c 0x63 99
	{0x38, 0x44, 0x44, 0x48, 0x7f}, // d 0x64 100
	{0x38, 0x54, 0x54, 0x54, 0x18}, // e 0x65 101
	{0x08, 0x7e, 0x09, 0x01, 0x02}, // f 0x66 102
	{0x0c, 0x52, 0x52, 0x52, 0x3e}, // g 0x67 103
	{0x7f, 0x08, 0x04, 0x04, 0x78}, // h 0x68 104
	{0x00, 0x44, 0x7d, 0x40, 0x00}, // i 0x69 105
	{0x20, 0x40, 0x44, 0x3d, 0x00}, // j 0x6a 106
	{0x00, 0x7f, 0x10, 0x28, 0x44}, // k 0x6b 107
	{0x00, 0x41, 0x7f, 0x40, 0x00}, // l 0x6c 108
	{0x7c, 0x04, 0x18, 0x04, 0x78}, // m 0x6d 109
	{0x7c, 0x08, 0x04, 0x04, 0x78}, // n 0x6e 110
	{0x38, 0x44, 0x44, 0x44, 0x38}, // o 0x6f 111
	{0x7c, 0x14, 0x14, 0x14, 0x08}, // p 0x70 112
	{0x08, 0x14, 0x14, 0x18, 0x7c}, // q 0x71 113
	{0x7c, 0x08, 0x04, 0x04, 0x08}, // r 0x72 114
	{0x48, 0x54, 0x54, 0x54, 0x20}, // s 0x73 115
	{0x04, 0x3f, 0x44, 0x40, 0x20}, // t 0x74 116
	{0x3c, 0x40, 0x40, 0x20, 0x7c}, // u 0x75 117
	{0x1c, 0x20, 0x40, 0x20, 0x1c}, // v 0x76 118
	{0x3c, 0x40, 0x30, 0x40, 0x3c}, // w 0x77 119
	{0x44, 0x28, 0x10, 0x28, 0x44}, // x 0x78 120
	{0x0c, 0x50, 0x50, 0x50, 0x3c}, // y 0x79 121
	{0x44, 0x64, 0x54, 0x4c, 0x44}, // z 0x7a 122
	{0x00, 0x08, 0x36, 0x41, 0x41}, // { 0x7b 123
	{0x00, 0x00, 0x7f, 0x00, 0x00}, // | 0x7c 124
	{0x41, 0x41, 0x36, 0x08, 0x00}, // } 0x7d 125
	{0x00, 0x06, 0x09, 0x09, 0x06}, // ~ 0x7e 126
	
	{0x7E, 0x11, 0x11, 0x11, 0x7E},	//__А (0xC0).
	{0x7F, 0x49, 0x49, 0x49, 0x33},	//__Б (0xC1).
	{0x7F, 0x49, 0x49, 0x49, 0x36},	//__В (0xC2).
	{0x7F, 0x01, 0x01, 0x01, 0x03},	//__Г (0xC3).
	{0xE0, 0x51, 0x4F, 0x41, 0xFF},	//__Д (0xC4).
	{0x7F, 0x49, 0x49, 0x49, 0x41},	//__Е (0xC5).
	{0x77, 0x08, 0x7F, 0x08, 0x77},	//__Ж (0xC6).
	{0x41, 0x49, 0x49, 0x49, 0x36},	//__З (0xC7).
	{0x7F, 0x10, 0x08, 0x04, 0x7F},	//__И (0xC8).
	{0x7C, 0x21, 0x12, 0x09, 0x7C},	//__Й (0xC9).
	{0x7F, 0x08, 0x14, 0x22, 0x41},	//__К (0xCA).
	{0x20, 0x41, 0x3F, 0x01, 0x7F},	//__Л (0xCB).
	{0x7F, 0x02, 0x0C, 0x02, 0x7F},	//__М (0xCC).
	{0x7F, 0x08, 0x08, 0x08, 0x7F},	//__Н (0xCD).
	{0x3E, 0x41, 0x41, 0x41, 0x3E},	//__О (0xCE).
	{0x7F, 0x01, 0x01, 0x01, 0x7F},	//__П (0xCF).
	{0x7F, 0x09, 0x09, 0x09, 0x06},	//__Р (0xD0).
	{0x3E, 0x41, 0x41, 0x41, 0x22},	//__С (0xD1).
	{0x01, 0x01, 0x7F, 0x01, 0x01},	//__Т (0xD2).
	{0x47, 0x28, 0x10, 0x08, 0x07},	//__У (0xD3).
	{0x1C, 0x22, 0x7F, 0x22, 0x1C},	//__Ф (0xD4).
	{0x63, 0x14, 0x08, 0x14, 0x63},	//__Х (0xD5).
	{0x7F, 0x40, 0x40, 0x40, 0xFF},	//__Ц (0xD6).
	{0x07, 0x08, 0x08, 0x08, 0x7F},	//__Ч (0xD7).
	{0x7F, 0x40, 0x7F, 0x40, 0x7F},	//__Ш (0xD8).
	{0x7F, 0x40, 0x7F, 0x40, 0xFF},	//__Щ (0xD9).
	{0x01, 0x7F, 0x48, 0x48, 0x30},	//__Ъ (0xDA).
	{0x7F, 0x48, 0x30, 0x00, 0x7F},	//__Ы (0xDB).
	{0x00, 0x7F, 0x48, 0x48, 0x30},	//__Ь (0xDC).
	{0x22, 0x41, 0x49, 0x49, 0x3E},	//__Э (0xDD).
	{0x7F, 0x08, 0x3E, 0x41, 0x3E},	//__Ю (0xDE).
	{0x46, 0x29, 0x19, 0x09, 0x7F},	//__Я (0xDF).

	{0x20, 0x54, 0x54, 0x54, 0x78},	//__а (0xE0).
	{0x3C, 0x4A, 0x4A, 0x49, 0x31},	//__б (0xE1).
	{0x7C, 0x54, 0x54, 0x28, 0x00},	//__в (0xE2).
	{0x7C, 0x04, 0x04, 0x0C, 0x00},	//__г (0xE3).
	{0xE0, 0x54, 0x4C, 0x44, 0xFC},	//__д (0xE4).
	{0x38, 0x54, 0x54, 0x54, 0x18},	//__е (0xE5).
	{0x6C, 0x10, 0x7C, 0x10, 0x6C},	//__ж (0xE6).
	{0x44, 0x54, 0x54, 0x28, 0x00},	//__з (0xE7).
	{0x7C, 0x20, 0x10, 0x08, 0x7C},	//__и (0xE8).
	{0x78, 0x42, 0x24, 0x12, 0x78},	//__й (0xE9).
	{0x7C, 0x10, 0x28, 0x44, 0x00},	//__к (0xEA).
	{0x20, 0x44, 0x3C, 0x04, 0x7C},	//__л (0xEB).
	{0x7C, 0x08, 0x10, 0x08, 0x7C},	//__м (0xEC).
	{0x7C, 0x10, 0x10, 0x10, 0x7C},	//__н (0xED).
	{0x38, 0x44, 0x44, 0x44, 0x38},	//__о (0xEE).
	{0x7C, 0x04, 0x04, 0x04, 0x7C},	//__п (0xEF).
	{0x7C, 0x14, 0x14, 0x14, 0x08},	//__р (0xF0).
	{0x38, 0x44, 0x44, 0x44, 0x00},	//__с (0xF1).
	{0x04, 0x04, 0x7C, 0x04, 0x04},	//__т (0xF2).
	{0x0C, 0x50, 0x50, 0x50, 0x3C},	//__у (0xF3).
	{0x30, 0x48, 0xFE, 0x48, 0x30},	//__ф (0xF4).
	{0x44, 0x28, 0x10, 0x28, 0x44},	//__х (0xF5).
	{0x7C, 0x40, 0x40, 0x7C, 0xC0},	//__ц (0xF6).
	{0x0C, 0x10, 0x10, 0x10, 0x7C},	//__ч (0xF7).
	{0x7C, 0x40, 0x7C, 0x40, 0x7C},	//__ш (0xF8).
	{0x7C, 0x40, 0x7C, 0x40, 0xFC},	//__щ (0xF9).
	{0x04, 0x7C, 0x50, 0x50, 0x20},	//__ъ (0xFA).
	{0x7C, 0x50, 0x50, 0x20, 0x7C},	//__ы (0xFB).
	{0x7C, 0x50, 0x50, 0x20, 0x00},	//__ь (0xFC).
	{0x28, 0x44, 0x54, 0x54, 0x38},	//__э (0xFD).
	{0x7C, 0x10, 0x38, 0x44, 0x38},	//__ю (0xFE).
	{0x08, 0x54, 0x34, 0x14, 0x7C},	//__я (0xFF). 
	/*
	{0x7e, 0x09, 0x09, 0x09, 0x7e}, // А 192
	{0x7F, 0x49, 0x49, 0x49, 0x71}, // Б
	{0x7f, 0x49, 0x49, 0x49, 0x36}, // В
	{0x7F, 0x01, 0x01, 0x01, 0x01}, // Г
	{0x60, 0x3E, 0x21, 0x3F, 0x60}, // Д
	{0x7f, 0x49, 0x49, 0x49, 0x41}, // Е
	{0x76, 0x08, 0x7F, 0x08, 0x76}, // Ж
	{0x21, 0x41, 0x45, 0x4b, 0x31}, // З
	{0x7F, 0x20, 0x10, 0x08, 0x7F}, // И
	{0x7E, 0x20, 0x11, 0x08, 0x7E}, // Й
	{0x7f, 0x08, 0x14, 0x22, 0x41}, // К
	{0x70, 0x0E, 0x01, 0x01, 0x7F}, // Л
	{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // М
	{0x7f, 0x08, 0x08, 0x08, 0x7f}, // Н
	{0x3e, 0x41, 0x41, 0x41, 0x3e}, // О
	{0x7F, 0x01, 0x01, 0x01, 0x7F}, // П
	{0x7f, 0x09, 0x09, 0x09, 0x06}, // Р
	{0x3e, 0x41, 0x41, 0x41, 0x22}, // С
	{0x01, 0x01, 0x7f, 0x01, 0x01}, // Т
	{0x07, 0x48, 0x48, 0x48, 0x7F}, // У
	{0x1C, 0x22, 0x7F, 0x22, 0x1C}, // Ф
	{0x63, 0x14, 0x08, 0x14, 0x63}, // Х
	{0x7F, 0x40, 0x40, 0x7F, 0xC0}, // Ц
	{0x07, 0x08, 0x08, 0x08, 0x7F}, // Ч
	{0x7F, 0x40, 0x7F, 0x40, 0x7F}, // Ш
	{0x7F, 0x40, 0x7F, 0x40, 0xFF}, // Щ
	{0x01, 0x7F, 0x48, 0x48, 0x70}, // Ъ
	{0x7F, 0x48, 0x70, 0x00, 0x7F}, // Ы
	{0x00, 0x7F, 0x48, 0x48, 0x70}, // Ь
	{0x22, 0x41, 0x49, 0x49, 0x3E}, // Э
	{0x7F, 0x08, 0x3E, 0x41, 0x3E}, // Ю
	{0x46, 0x29, 0x19, 0x09, 0x7F}, // Я 223

	{0x20, 0x54, 0x54, 0x54, 0x78}, //a 224
	{0x3c, 0x4a, 0x4a, 0x49, 0x31}, //б
	{0x7c, 0x54, 0x54, 0x28, 0x00}, //в
	{0x7c, 0x04, 0x04, 0x04, 0x0c}, //г
	{0xe0, 0x54, 0x4c, 0x44, 0xfc}, //д
	{0x38, 0x54, 0x54, 0x54, 0x18}, //e
	{0x6c, 0x10, 0x7c, 0x10, 0x6c}, //ж
	{0x44, 0x44, 0x54, 0x54, 0x28}, //з
	{0x7c, 0x20, 0x10, 0x08, 0x7c}, //и
	{0x7c, 0x41, 0x22, 0x11, 0x7c}, //й
	{0x7c, 0x10, 0x28, 0x44, 0x00}, //к
	{0x20, 0x44, 0x3c, 0x04, 0x7c}, //л
	{0x7c, 0x08, 0x10, 0x08, 0x7c}, //м
	{0x7c, 0x10, 0x10, 0x10, 0x7c}, //н
	{0x38, 0x44, 0x44, 0x44, 0x38}, //o
	{0x7c, 0x04, 0x04, 0x04, 0x7c}, //п
	{0x7C, 0x14, 0x14, 0x14, 0x08}, //p
	{0x38, 0x44, 0x44, 0x44, 0x20}, //c
	{0x04, 0x04, 0x7c, 0x04, 0x04}, //т
	{0x0C, 0x50, 0x50, 0x50, 0x3C}, //у
	{0x30, 0x48, 0xfc, 0x48, 0x30}, //ф
	{0x44, 0x28, 0x10, 0x28, 0x44}, //x
	{0x7c, 0x40, 0x40, 0x40, 0xfc}, //ц
	{0x0c, 0x10, 0x10, 0x10, 0x7c}, //ч
	{0x7c, 0x40, 0x7c, 0x40, 0x7c}, //ш
	{0x7c, 0x40, 0x7c, 0x40, 0xfc}, //щ
	{0x04, 0x7c, 0x50, 0x50, 0x20}, //ъ
	{0x7c, 0x50, 0x50, 0x20, 0x7c}, //ы
	{0x7c, 0x50, 0x50, 0x20, 0x00}, //ь
	{0x28, 0x44, 0x54, 0x54, 0x38}, //э
	{0x7c, 0x10, 0x38, 0x44, 0x38}, //ю
	{0x08, 0x54, 0x34, 0x14, 0x7c}, //я 255
*/
};
по этой ссылке можно посмотреть как это работает https://youtu.be/L_biQ_cXN-0

Re: MSMDClock_displey

Добавлено: 31 дек 2019, 10:08
Sergey2055
Всем привет. Проект дисплея закончен. Выкладываю почти финальные фотки и код. Возможно код еще будет модернизироваться но это уже другая история.

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

#include <Time.h>
#include <TimeLib.h>

#define MY_DEBUG
#define MY_NODE_ID AUTO
#define MY_PARENT_NODE_ID AUTO
#define MY_RADIO_RF24
#define MY_RF24_PA_LEVEL RF24_PA_MAX

#include <MySensors.h>
#include <avr/wdt.h>
#include <EEPROM.h>
const int timeZone = 3;     // мск

#define SKETCH_NAME "MSMDClock_displey"
#define SKETCH_MAJOR_VER "1"
#define SKETCH_MINOR_VER "0"

#define SID_LIGHT         1
#define SID_TEMP          2
#define SID_HUM           3
#define SID_MSMD          210
#define SID_NodeID        211
#define SID_FREQ          212
#define SID_PARENT_SELECT 213

#define MaxByte  0xFF
#define MaxWord  0xFFFF

#define mFreq     8

#define cGateAdr 0
#define DEF_FREQUENCY 1 // min
#define DEB_SWITCH_PIN  3
#define MAXTRY 5 //Количество попыток отправки пакета.
#define PAUSETX 100

unsigned long Freq = DEF_FREQUENCY*60*1000ul, oldFreq = 0;

void(* resetFunc) (void) = 0;

#include "FastLED.h"  //Подключаем библиотеку FastLED
#define NUM_LEDS 300  //Определяем количество светодиодов на табло
#define DATA_PIN 5   //Пин, по которому происходит управление табло
#define ROWS 10        //Количество строк табло
#define COLS 30       //Количество столбцов табло
#define minRGB 2      //Минимальная яркость светодиодов в обычном режиме работы
#define colorOrder GRB//Порядок цветов для FastLED
#include "fonts.h"


#define C_BLACK 0x000000
#define C_GREEN 0x00FF00
#define C_RED 0xFF0000
#define C_BLUE 0x0000FF
#define C_PURPLE 0xFF00FF
#define C_YELLOW 0xFFFF00
#define C_CYAN 0x00FFFF
#define C_WHITE 0xFFFFFF

unsigned long color  =  C_WHITE, color2, oldinterval2, time1, mil;

CRGB leds[NUM_LEDS]; //Массив светодиодов для работы с FastLED
int c,br,a=0,n=0,xStep, interval2 = 1000, Temp, Hum, Time_minute, Time_hour, Light;  //Служебные переменные
boolean flag=true, flag1, first=true;  //Служебные переменные
byte Hour_high, Houl_low, Min_high, Min_low, h, m, s, T1, flag2;

//Функция зажигает светодиод n цветом r,g,b (выключенный светодиод n это частный случай зажигания светодиода n цветом 0,0,0)
void setLed(int n,byte r,byte g,byte b) {
    //n = n+ COLS;
    leds[n].r=r;
    leds[n].g=g;
    leds[n].b=b;
}
 void clear_displey (){
     for (int m=0; m<NUM_LEDS; m++) {
          leds[m].r = 0;
          leds[m].g = 0;
          leds[m].b = 0;}
          FastLED.show();  //Синхронизируем табло с массивом leds (обновляем информацию на нём в соответствии с содержимым массива)
}

//Функция выводит текущее время в массив светодиодов leds[], используя вышеописанные функции PutDigit и putDots.
void putTime() {
  if(flag2 == 1) {clear_displey ();}

                conversion_text(4,1,(Min_low)+48,color);
                conversion_text(3,1,(Min_high)+48,color);
                conversion_text(2,1,':',color2);
                conversion_text(1,1,(Houl_low)+48,color);
                conversion_text(0,1,(Hour_high)+48 ,color);

               // putDots(r,g,b);
}


MyMessage msgLight(SID_LIGHT, V_LEVEL);
MyMessage msgTemp(SID_TEMP, V_TEMP);
MyMessage msgHum(SID_HUM,   V_HUM);
MyMessage msgFreq(SID_FREQ, V_VAR1);

 // String  var = getValue( StringVar, ',', 2); // if  a,4,D,r  would return D        
String getValue(String data, char separator, int index){
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length();

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
        return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}  // END

void before(){  
  wdt_disable();

  pinMode(DEB_SWITCH_PIN, INPUT_PULLUP);  
  if (digitalRead(DEB_SWITCH_PIN) == LOW){    
    
    for (int i=0;i<512;i++)
      EEPROM.write(i, 0xFF);   
  }


  //=== Read from memory
  // Freq
  uint8_t fBVal = loadState(mFreq);
  if (fBVal != MaxByte) {    
    Freq = int(fBVal)*60*1000ul;
  }
  
}    

void presentation() { 
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);

  present(SID_LIGHT, S_LIGHT_LEVEL, "Lux-data");
  wait(300);    
  present(SID_TEMP,   S_TEMP,    "Temp");
  wait(300);  
  present(SID_HUM,    S_HUM,     "HUM");
  wait(300);       
  present(SID_MSMD,   S_CUSTOM, "a00678cb4bc49c5e");
  wait(300);
  present(SID_NodeID, S_CUSTOM, "Node ID");
  wait(300);
  present(SID_FREQ,   S_CUSTOM, "NODE FREQ MINUTE");
  wait(300);
  present(SID_PARENT_SELECT, S_CUSTOM, "NODE_PARENT_SELECT");
} 

void setup() {
  wdt_enable(WDTO_8S);
    FastLED.addLeds<WS2812B, DATA_PIN, colorOrder>(leds, NUM_LEDS); //Инициализируем библиотеку FastLED с заданными нами параметрами. Теперь массив leds - это данные о всех наших пикселях на табло.
    clear_displey ();
    FastLED.setBrightness(255); //Устанавливаем максимально возможную яркость (диапазон для каждого канала 0-255)
   // request_data();  
    requestTime();
    wait(2000);
    request(2, V_TEMP);
    wait(1000);    
    request(3, V_HUM);
    wait(1000);
}

void loop (){      
  wdt_reset();
 if(Light < 50){
   FastLED.setBrightness(10); //Устанавливаем яркость на максимум, чтобы эти значения соответствовали себе (иначе FastLED их пропорционально затемнит)
 }
 else{
   if(Light > 50){
   FastLED.setBrightness(150); //Устанавливаем яркость на максимум, чтобы эти значения соответствовали себе (иначе FastLED их пропорционально затемнит)
 }
 }
 
  
 if(weekday() == 1 && hour() == 0 && minute() == 0){
    requestTime();
    wait(2000);
 }
 
//ПП обработки часов
  if (millis() - mil > 1000 || first){
      mil = millis();
      //Serial.println(hour());
      //Serial.println(minute());
      s++; if(s == 60) {s = 0; color_new(xStep);}
      if(flag2 == 0) flag2 = 1;
      first=false; //Всё, уже не впервые
      if(s < 45){
        timeget();
        flag2 = 2;
      flag1 = !flag1;
      if(flag1 == 1){color2 = color;} else {color2 = C_BLACK;}
      }
      else if(s < 50) { dateget(); flag2 = 3;}    
             else if(s < 55) { tempget(); flag2 = 4;} 
               else if(s < 60) { humget(); flag2 = 1;}
      
   }
 
}

void receiveTime(unsigned long controllerTime) {
  controllerTime = controllerTime + timeZone * SECS_PER_HOUR;
  setTime(controllerTime);

}

void receive(const MyMessage &message) {

  if (message.isAck()) {
    return;
  }
 
  String Str = ""; bool z;
  uint8_t Dest = message.sender;

  // Request
  if (mGetCommand(message) == C_REQ) {

    switch (message.sensor) {

    case SID_FREQ:
        send( msgFreq.set(Freq / (60*1000)) );
       break;
    }
    return;
  }

  // Set NULL date (if empty sensors)
  if (strlen(message.getString()) == 0) {
    return;
  }

  switch (message.sensor) { 

  case SID_LIGHT:
    Light = message.getInt();  
    break;    

  case SID_TEMP:
    Temp = message.getInt();  
    break;  

  case SID_HUM:
    Hum = message.getInt();  
    break;    
  
  case SID_FREQ:
    Freq = message.getByte() * 60*1000ul;
    saveState(mFreq, message.getByte());    
    break;

  // NODE_NEW_ID; type == V_VAR1
  case SID_NodeID:
    byte Node_ID = message.getByte();
      hwWriteConfig(EEPROM_NODE_ID_ADDRESS, Node_ID);
      resetFunc();
      break;

    // NODE_NEW_PARENT; type == V_VAR1
  case SID_PARENT_SELECT:
    byte Node_Parent = message.getByte();
      hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, Node_Parent);
      resetFunc();
      break;
  }  
}

void tempget (){
 if(flag2 == 3) {clear_displey ();}
char b[3];
String str;
str=String(Temp);
str.toCharArray(b,3);
if(str[2] == 0){
   if(str[1] == 0){
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,('~'),color);
      conversion_text(3,1,('C'),color);      
   }
   else
   {  
      conversion_text(0,1,(str[0]),color);
      conversion_text(1,1,(str[1]),color);
      conversion_text(2,1,('~'),color);
      conversion_text(3,1,('C'),color);      
   }
}
else {
      conversion_text(0,1,(str[0]),color);
      conversion_text(1,1,(str[1]),color);
      conversion_text(2,1,(str[2]),color);
      conversion_text(3,1,('~'),color);
      conversion_text(4,1,('C'),color);
}
FastLED.show(); //Синхронизируем табло с массивом leds
}
void humget () {
 if(flag2 == 4) {clear_displey (); xStep++; if(xStep == 7){xStep = 0;}}
char b[3];
String str;
str=String(Hum);
str.toCharArray(b,3);
if(str[2] == 0){
   if(str[1] == 0){
      conversion_text(2,1,(str[0]),color);
      conversion_text(3,1,('%'),color);      
   }
   else
   {  
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,(str[1]),color);
      conversion_text(3,1,('%'),color);      
   }
}
else {
      conversion_text(1,1,(str[0]),color);
      conversion_text(2,1,(str[1]),color);
      conversion_text(3,1,(str[2]),color);
      conversion_text(4,1,('%'),color);

}
FastLED.show(); //Синхронизируем табло с массивом leds
}

void dateget(){
      if(flag2 == 2) {clear_displey ();}
      conversion_text(0,1,(day() / 10)+48,color);
      conversion_text(1,1,(day() % 10)+48,color);
      conversion_text(2,1,('.'),color);
      conversion_text(3,1,(month() / 10)+48,color);    
      conversion_text(4,1,(month() % 10)+48,color);
      FastLED.show(); //Синхронизируем табло с массивом leds
}

void request_data (){
    request(SID_TEMP, V_TEMP);
    wait(1000, SID_TEMP, V_TEMP);
    request(SID_HUM, V_HUM);
    wait(1000, SID_HUM, V_HUM);
    request(SID_LIGHT, V_LEVEL);
    wait(1000, SID_LIGHT, V_LEVEL);    

}

void timeget () {
      Hour_high = hour() / 10;
      Houl_low = hour() % 10;
      Min_high = minute() % 60 / 10;
      Min_low = minute() % 10;
      putTime();
      FastLED.show(); //Синхронизируем табло с массивом leds
}

//функция смены цвета
void color_new(int i){
  switch (i) {
    case 1:
      color  = C_WHITE;
      break;
    case 2:
      color  = C_GREEN;
      break;
    case 3:
      color  = C_RED;
      break;
    case 4:
      color  = C_BLUE;
      break;
    case 5:
      color  = C_PURPLE;
      break;
    case 6:
      color  = C_YELLOW;
      break;
    case 7:
      color  = C_CYAN;
      break;   
  }
}


void conversion_text(int column, int line, byte text_type, unsigned long color_text){
  byte a; 
  byte r, g, b;
for (int i = 0; i<5; i++){
  a = 0; 
  a = read_text((byte)text_type, i);
  for(int k = 0; k < 7; k++){
    bool s = 0;
    s = bitRead(a,0);
    if(s == 1){r = color_text >> 16; g = color_text >> 8; b = color_text;} 
      else {r = 0; g = 0; b = 0;}
        if(column < COLS) {setLed((column*6+i+(k*COLS)+(line*COLS)),r,g,b);} 
        a = a >> 1;
  }
 }
}

uint8_t read_text (uint8_t font, uint8_t row){ 
  font = font - '0' + 16;   // перевод код символа из таблицы ASCII в номер согласно нумерации массива
  if (font <= 90) return pgm_read_byte(&(fontHEX[font][row]));     // для английских букв и символов
     else if (font >= 112 && font <= 159) {return pgm_read_byte(&(fontHEX[font - 17][row]));}     // для русских
              else if (font >= 96 && font <= 111) {return pgm_read_byte(&(fontHEX[font + 47][row]));}
                   else{return pgm_read_byte(&(fontHEX[font][row]));}
}


Лента собрана по картинке ниже, а запитана с верхнего левого угла.
1.jpg
1.jpg (75.31 КБ) 7650 просмотров
Ниже представлены фото конструкции начинки дисплея.

тут можно посмотреть как это выглядет в работе https://youtu.be/7a8e8T0IQhc