St7735 много или имитация разных часов

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

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

1 лайк

Вы вообще о чем?
Для того, что делает Лилик, нужны ПК, Ардуина, 4 TFT экрана, USB шнур, макетная плата, провода…
А для того, что предлагаю я, только ПК.
Это дешевле!
При чем здесь провода за десятки тысяч рублей?

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

Тогда ради чего вообще вся эта тема?

Не только для достоверности, но также для скорости, качества и более объективного анализа. На ПК можно расположить рядышком результаты до и после обработки. Можно показать результат вычитания одного изображения из другого и т.п.

Для меня это тяжело…написать такое приложение…Это вообще отдельная тема работы :slight_smile:

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

Это самое тяжёлое. Искать между:
преобразование
и таким:

R=(cvet/2048)*2;G=(cvet%2048)/32;B=(cvet%32)*2;// 0-63
float H=0;//Hue
if(R>G&&G>=B||R>=G&&G>B){ H=(G-B)/(R-B); if(sat<=1.0){B=B+(R-B)*sat;}else{B=porog_(B-sat,0);} G=H*(R-B)+B;}
if(G>B&&B>=R||G>=B&&B>R){ H=(B-R)/(G-R); if(sat<=1.0){R=R+(G-R)*sat;}else{R=porog_(R-sat,0);} B=H*(G-R)+R;}
if(B>R&&R>=G||B>=R&&R>G){ H=(R-G)/(B-G); if(sat<=1.0){ G=G+(B-G)*sat;}else{G=porog_(G-sat,0);} R=H*(B-G)+G;}
if(R>B&&B>=G||R>=B&&B>G){ H=(B-G)/(R-G); if(sat<=1.0){ G=G+(R-G)*sat;}else{G=porog_(G-sat,0);} B=H*(R-G)+G;}
if(G>R&&R>=B||G>=R&&R>B){ H=(R-B)/(G-B); if(sat<=1.0){B=B+(G-B)*sat;}else{B=porog_(B-sat,0);} R=H*(G-B)+B;}
if(B>G&&G>=R||B>=G&&G>R){ H=(G-R)/(B-R); if(sat<=1.0){R=R+(B-R)*sat;}else{R=porog_(R-sat,0);} G=H*(B-R)+R;}
cvet=(R/2)*2048+G*32+B/2;// ослабление насыщения цветом и усиление насыщения sat=1.0-0.0-60

int porog_ (int d,int min_){
 if(d<min_){return min_;}
 else{
 return d;
 }
}

Во-первых: вы таки не поняли, что десятки тысяч - это за подставки, а провода идут на порядки дороже.

Во-вторых:

вот это и напоминает высказывания “филов” - “возьмите всё лучшее и дорогое”, а в реальности приходится брать что есть. А этого “есть” крайне мало и в “так-себе” качестве, ибо снимать или рисовать цифры с реальных дисплеев мало желающих.

Отнюдь.
Там в стандартный шаблон добавляется одна строка и тот код, с которым ты собираешься экспериментировать. Разумеется, если это формат bmp.

Вот, а под виндами это не нужно.

Честно говоря, не понимаю, что общего между “возьмите всё лучшее и дорогое” и “замените дешевое на лучшее и бесплатное”.

Не понял где и как, попробовал в “Процессинге”.


Справа исходник, слева инверсия цветов.

PImage img=createImage(128, 160, RGB);

void setup() {
  size(384, 160);
  img = loadImage("ris_1.jpg");
 image(img, 256, 0); 
}

void draw() {
  loadPixels(); 
  img.loadPixels();

  for (int y = 0; y < img.height; y++) {
    for (int x = 0; x <img.width ; x++) {
        int imageLoc = x + y*img.width;
        int displayLoc = x + y*width;
      
      float r = red(img.pixels[imageLoc]);
      float g = green(img.pixels[imageLoc]);
      float b = blue(img.pixels[imageLoc]);
      
      pixels[displayLoc] =  color(255-r, 255-g, 255-b); // Установить преобразованный пиксель дисплея в соответствии пикселю изображения
    }
  }
  updatePixels();
save("kadr.png");
}

И кадр из приложения…
kadr

Какой процессинг?
Создаете обычное приложение Win32 и в фрагмент

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            BF.draw(hWnd, hdc);
            // TODO: Добавьте сюда любой код прорисовки, использующий HDC...
            EndPaint(hWnd, &ps);
        }
        break;

Добавляеие примерно такую строку:
int res = StretchDIBits(hdc, BORDER_COMM, BORDER_COMM, currDx, currDy, 0, 0, currDx, currDy, screen, (BITMAPINFO*)&bih, DIB_RGB_COLORS, SRCCOPY);, где screen - это Ваша картинка (массив пикселей), который Вы можете обрабатывать как угодно.

VID_20231122_170547-min
Вдарил морозец, пошёл ложиться снег… индикатор наступающего очередного года как альтернатива гирлянде :slight_smile:

1 лайк

Красота!

Добавил опцию прозрачность слоёв.


Наверно будет полезна при плавной смене картинок.

1 лайк

Если не жалко, по подробнее про слои

Не жалко. Принцип прост. Есть два массива-картинки. Из каждого массива берутся соответствующие цвета-пиксели (двухбайтное число). Далее из них извлекаются компоненты цвета - R,G,B. Преобразуются в компоненты общего пикселя (для двух картинок с учётом прозрачности) по формуле:

Формула объединения C1 = (R1,G1,B1)и C2 = (R2,G2,B2)в новый цвет C3 , где C2 накладывается поверх C1 с непрозрачностью p, обычно равна R3= (1-p)*R1 + p*R2, G3=(1-p)*G1 + p*G2, B3=(1-p)*B1 + p*B2 ).

Затем вновь “сливаются” в два байта - новый цвет пикселя и выводятся на дисплей. p - прозрачность, от 0.00 до 1.00. Вариант кода:

//вывод картинок на дисплеи
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include "ris_0.h"//файл хранения массивов 

#define TFT_CS     5   //не используется по назначению
#define TFT_RST    13 // (RES)
#define TFT_DC     12 // (RS)
#define TFT_CS1    4   // выводы для коммутации дисплеев
#define TFT_CS2    26
#define TFT_CS3    25
#define TFT_CS4    17
// TFT_SCL 18   
// TFT_SDA 23 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);//
#define TFT_SCLK 18   // set these to be whatever pins you like!
#define TFT_MOSI 32   // set these to be whatever pins you like!
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);//

const byte z=0;//определяет вид используемых цифр
long Y=0;//
void setup() {
 pinMode(TFT_CS1, OUTPUT);
 pinMode(TFT_CS2, OUTPUT);
 pinMode(TFT_CS3, OUTPUT);
 pinMode(TFT_CS4, OUTPUT);
 digitalWrite(TFT_CS1,LOW);
 digitalWrite(TFT_CS2,LOW);
 digitalWrite(TFT_CS3,LOW);
 digitalWrite(TFT_CS4,LOW);
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(2);
 tft.fillScreen(tft.Color565(0,0,0));
digitalWrite(TFT_CS1,LOW);drawFoto(0,0,ris_1,ris_0,128,160,0.0);digitalWrite(TFT_CS1,HIGH);
digitalWrite(TFT_CS2,LOW);drawFoto(0,0,ris_1,ris_0,128,160,0.33);digitalWrite(TFT_CS2,HIGH);
digitalWrite(TFT_CS3,LOW);drawFoto(0,0,ris_1,ris_0,128,160,0.66);digitalWrite(TFT_CS3,HIGH);
digitalWrite(TFT_CS4,LOW);drawFoto(0,0,ris_1,ris_0,128,160,1.0);digitalWrite(TFT_CS4,HIGH);
  }
void loop() {

}
//////////////////////////////////////////
void drawFoto(int x,int y, const uint8_t *bitmap_1,const uint8_t *bitmap_2,int w,int h,float p) {//функция вывода фотокартинки
if(x<0||x+w>128||y<0||y+h>160){return;} 
 tft.setAddrWindow(x,y,x+w-1,y+h-1);
 SPI.beginTransaction(SPISettings(40000000, MSBFIRST, SPI_MODE0));
  digitalWrite(TFT_DC, HIGH);
  digitalWrite(TFT_CS, LOW); 
 for(int j=0; j<h; j++) {
    for(int i=0; i<2*w; i=i+2) {
      //
        int cvet_1=256*bitmap_1[i+1+j*2*w]+bitmap_1[i+j*2*w];
        int cvet_2=256*bitmap_2[i+1+j*2*w]+bitmap_2[i+j*2*w];
        int R_1=cvet_1/2048;int G_1=(cvet_1%2048)/32;int B_1=cvet_1%32;int R_2=cvet_2/2048;int G_2=(cvet_2%2048)/32;int B_2=cvet_2%32;
        R_1=(1.00-p)*R_1 + p*R_2; G_1=(1.00-p)*G_1 + p*G_2; B_1=(1.00-p)*B_1 + p*B_2;
        cvet_1=R_1*2048+G_1*32+B_1;//R=0-31,G=0-63,B=0-31 
        //
    SPI.transfer(cvet_1/256);SPI.transfer(cvet_1%256);
    }
  }
  digitalWrite(TFT_CS, HIGH);
  SPI.endTransaction();
 ///  
}
//////////////////////



Спасибо, сам работаю в фотошопе поэтому “слой”-нечто сакральное

VID_20231126_131716
Вариант анимации всего из двух картинок.

Мне кажется, или левая злее чем правая?

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