st7735 160 на 128 подсветка барахлит

lilik
Offline
Зарегистрирован: 19.10.2017

Пришла пара дисплеев таких

С подключением разобрался, скетчи примеров работают, с подсветкой не ясно. При включении внешнего резистора 220 ом экран один тускло, другой никак не горит. Вывод информации сопровождается мерцанием и сбоями картинки у первого. Если включать без резистора всё светит ярко и чётко. Устойчиво, почти, работает при 27 омах. Очень хорошо при питании от аккумулятора всё работает. Почему так происходит? В цепях выводов информационных стоят резисторы по 1,5 кОм. Нахрена они надо?(все ставят зачем то) 

:)

Как грамотно управлять светодиодом, или может просто выбраковку прислали?

 

 

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>


// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS     10
#define TFT_RST    9  // you can also connect this to the Arduino reset
                      // in which case, set this #define pin to 0!
#define TFT_DC     8

// Option 1 (recommended): must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);


float p = 3.1415926;

void setup(void) {
  Serial.begin(9600);
  Serial.print("Hello! ST7735 TFT Test");

  // Use this initializer if you're using a 1.8" TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab

  // Use this initializer (uncomment) if you're using a 1.44" TFT
 // tft.initR(INITR_144GREENTAB);   // initialize a ST7735S chip, black tab

  Serial.println("Initialized");

  uint16_t time = millis();
  tft.fillScreen(ST7735_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST7735_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST7735_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST7735_GREEN);
  delay(500);

  // line draw test
  testlines(ST7735_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST7735_RED, ST7735_BLUE);
  delay(500);

  testdrawrects(ST7735_GREEN);
  delay(500);

  testfillrects(ST7735_YELLOW, ST7735_MAGENTA);
  delay(500);

  tft.fillScreen(ST7735_BLACK);
  testfillcircles(10, ST7735_BLUE);
  testdrawcircles(10, ST7735_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);
}

void loop() {
  tft.invertDisplay(true);
  delay(500);
  tft.invertDisplay(false);
  delay(500);
}

void testlines(uint16_t color) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
  }
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST7735_BLACK);
  int color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST7735_BLACK);
  int color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST7735_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST7735_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST7735_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST7735_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST7735_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST7735_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST7735_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_GREEN);
}
/*
  Arduino TFT text example

  This example demonstrates how to draw text on the
  TFT with an Arduino. The Arduino reads the value
  of an analog sensor attached to pin A0, and writes
  the value to the LCD screen, updating every
  quarter second.

  This example code is in the public domain

  Created 15 April 2013 by Scott Fitzgerald

  http://www.arduino.cc/en/Tutorial/TFTDisplayText

 */

#include <TFT.h>  // Arduino LCD library
#include <SPI.h>

// pin definition for the Uno
#define cs   10
#define dc   8
#define rst  9

// pin definition for the Leonardo
// #define cs   7
// #define dc   0
// #define rst  1

// create an instance of the library
TFT TFTscreen = TFT(cs, dc, rst);

// char array to print to the screen
char sensorPrintout[5];

void setup() {

  // Put this line at the beginning of every sketch that uses the GLCD:
  TFTscreen.begin();

  // clear the screen with a black background
  TFTscreen.background(0, 0, 0);

  // write the static text to the screen
  // set the font color to white
  TFTscreen.stroke(255, 255, 255);
  // set the font size
  TFTscreen.setTextSize(2);
  // write the text to the top left corner of the screen
  TFTscreen.text("Sensor Value :\n ", 0, 0);
  // ste the font size very large for the loop
  TFTscreen.setTextSize(5);
}

void loop() {

  // Read the value of the sensor on A0
  String sensorVal = String(analogRead(A0));

  // convert the reading to a char array
  sensorVal.toCharArray(sensorPrintout, 5);

  // set the font color
  TFTscreen.stroke(255, 255, 255);
  // print the sensor value
  TFTscreen.text(sensorPrintout, 0, 20);
  // wait for a moment
  delay(250);
  // erase the text you just wrote
  TFTscreen.stroke(0, 0, 0);
  TFTscreen.text(sensorPrintout, 0, 20);
}

 

lilik
Offline
Зарегистрирован: 19.10.2017

Неясно почему верхние схемы преобладают над нижними?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. 220 Ом для подсветки, очевидно, слишком много. Разумный диапазон 10-47 Ом.

2. Я так и не смог установить соответствия между распиновкой  в нулевом сообщении и схемами в первом.

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

4. Резисторы в цепях управления, очевидно, связаны с тем, что дисплей 3.3-вольтовый.

 

*. Вспомнил, что 47 Ом - это я ставил на монохромный дисплей. Для цветного, очевидно, ток должен быть втрое выше, т.е. номинал вряд ли должен превышать 20 Ом.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

andriano диод подсветки один, так что номинал резистора +- одинаковый для цветного и монохромного.

ТС ШИМ подайте туда и регулируйте яркость как хотите.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Komandir пишет:

andriano диод подсветки один, так что номинал резистора +- одинаковый для цветного и монохромного.

ТС ШИМ подайте туда и регулируйте яркость как хотите.

Дело не в светодиоде, а в матрице: монохромная матрица может пропускать до 50% падающего на нее света, а цветная - не более 16.6%. Для одинаковой яркости на выходе свет от светодиода должен быть в три раза ярче для цветной матрицы.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Убедительно.

lilik
Offline
Зарегистрирован: 19.10.2017

andriano пишет:

2. Я так и не смог установить соответствия между распиновкой  в нулевом сообщении и схемами в первом.

4. Резисторы в цепях управления, очевидно, связаны с тем, что дисплей 3.3-вольтовый.

Вот так заработал на тест-скетче нормально. Зачем тогда стабилизатор ему на плате? Почему токаограничительный резистор только 3,3 Ома? Подсветка жрёт 29 мА, сам дисплей около 0,1 мА. Зачем резисторы в схеме?, если токаограничительные почему малый номинал, не 100 кОм, а порядка одного. Если ограничивают напряжение, где делители? Как уменьшить число соединений?

Как всегда одни вопросы. А дисплей очень такой доступный, всего 130 рублей.

#include <TFT.h>  // Arduino LCD library
#include <SPI.h>

// pin definition for the Uno
#define cs   10
#define dc   8
#define rst  9
// create an instance of the library
TFT TFTscreen = TFT(cs, dc, rst);

// char array to print to the screen
char sensorPrintout[5];

void setup() {
// Порт управления подсветкой экрана
  pinMode(6,OUTPUT);
  analogWrite(6,100);
  
  // Put this line at the beginning of every sketch that uses the GLCD:
  TFTscreen.begin();

  // clear the screen with a black background
  TFTscreen.background(0, 0, 0);

  // write the static text to the screen
  // set the font color to white
  TFTscreen.stroke(255, 255, 255);
  // set the font size
  TFTscreen.setTextSize(2);
  // write the text to the top left corner of the screen
  TFTscreen.text("Sensor Value :\n ", 0, 0);
  // ste the font size very large for the loop
  TFTscreen.setTextSize(5);
}

void loop() {

  // Read the value of the sensor on A0
  String sensorVal = String(analogRead(A0));

  // преобразуйте чтение в массив символов
  sensorVal.toCharArray(sensorPrintout, 5);

  // установите цвет шрифта
  TFTscreen.stroke(0, 255, 50);
  //выведите значение датчика
  TFTscreen.text(sensorPrintout, 0, 20);
  //
  delay(300);
  // сотрите текст, который вы только что написали
  TFTscreen.stroke(0, 0, 0);
  TFTscreen.text(sensorPrintout, 0, 20);
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lilik пишет:

Зачем тогда стабилизатор ему на плате?

Очевидно затем, что ему нужно 3.3 В.

Цитата:

Почему токаограничительный резистор только 3,3 Ома?

Очевидно, разработчик решил, что это - оптимальная величина.

Цитата:

Зачем резисторы в схеме?

Уже было отвечено (4).

Цитата:
, если токаограничительные почему малый номинал, не 100 кОм, а порядка одного.

Оптимальное значение. Если будут сотни кОм - будет реагировать на любые помехи.

Цитата:
Если ограничивают напряжение, где делители?

В качестве нижнего плеча делителей используются входные схемы контроллера (Вы же сами хотите уменьшения числа деталей)

Цитата:
Как уменьшить число соединений?
Как увеличить - легко: добавить те самые резисторы в делители.

Цитата:

Как всегда одни вопросы.

Ну так нужно задавать осмысленные вопросы и читать ответы, а не пропускать их мимо внимания.

Цитата:
А дисплей очень такой доступный, всего 130 рублей.
Только очень мелкий. У меня вот от 1.8, 2.0, 2.2 ни разу не использовались - так и лежат в коробке. А используются в основном либо двухстрочные текстовые, либо монохромные 128х64, либо цветные в диапазоне 2.4-4.0.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

я тут намедни протупил. без резисторов включил (использовал для ESP ранее), так что теперь - был у меня один дисплей )))
ЗЫ первые потери да 6 лет...

lilik
Offline
Зарегистрирован: 19.10.2017

Если экран чик один можно так сократить резисторы. Удивительно, но такой вариант схемы работает надёжно. Замерял авометром электронным, на резисторе к SDA падает 0,8-0,9В при питании от 5 В и всего 0,06 при питании от аккума (3,8В). Как то я в смущении от их пользы, но убирать не стану :)

lilik
Offline
Зарегистрирован: 19.10.2017

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

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Офф: lilik, не в службу, скинь ссылку на свою тему, где ты шары на адресных светодиодах делал ))

lilik
Offline
Зарегистрирован: 19.10.2017

v258 пишет:
Офф: lilik, не в службу, скинь ссылку на свою тему, где ты шары на адресных светодиодах делал ))

https://arduino.ru/forum/proekty/zalivaem-shary-k-prazdniku

 

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Спасибо))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lilik пишет:

 

 

Отрисовка медленней чем на SSD1306.

Кто бы мог подумать, что 16 бит на пиксель окажется больше, чем 1 бит на пиксель!

lilik
Offline
Зарегистрирован: 19.10.2017

А скорость передачи ?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

И там, и там передача последовательная. Так что даже 4 Мбит/с SPI против 400 кбит/ I2C не могут изменить соотношение на обратное. 

И, кстати, 1306 вполне способен работать по I2C на 2 Мбит/с. Да и с интерфейсом SPI они бывают. Так что в принципе возможности разгона у 1306 выше.

lilik
Offline
Зарегистрирован: 19.10.2017

Да, в целом не шустро, но если смотреть в прищур, то даже пламя похоже на пламя.

Argus19
Offline
Зарегистрирован: 08.05.2022

 lilik, Сколько памяти кушают скетчи?

 

lilik
Offline
Зарегистрирован: 19.10.2017

Argus19 пишет:

 lilik, Сколько памяти кушают скетчи?

 

Секундомер 38% памяти и 6% динамической, узоры 25 и 5 соответственно. 

Argus19
Offline
Зарегистрирован: 08.05.2022

 Спасибо.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Это у 328й?

lilik
Offline
Зарегистрирован: 19.10.2017

Да.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

Argus19 пишет:

 lilik, Сколько памяти кушают скетчи?

Секундомер 38% памяти и 6% динамической, узоры 25 и 5 соответственно. 

а можешь код секундомера выложить?

lilik
Offline
Зарегистрирован: 19.10.2017
// СЕКУНДОМЕР
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9  
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

float a = 0.00; // переменная для угла поворота стрелки
float aa = 0.00; // переменная для угла поворота стрелки (предыдущее значение)
int str = 55; //длина стрелки в пикселях
byte sek=16;//

void setup(void) {
  // Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(1);//ориентация экрана
 tft.drawCircle(80,64,63,ST7735_WHITE );//обод секундомера
 tft.drawCircle(80,64,62,ST7735_WHITE );
 tft.drawCircle(80,64,61,ST7735_WHITE );
  
}
void loop() {
 // 
 aa = a;  
   // tft.drawLine(80, 64, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки-отрезка
   tft.drawLine(80+ cos(aa+1.5)*str*0.1, 64+ sin(aa+1.5)*str*0.1, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки
   tft.drawLine(80+ cos(aa-1.5)*str*0.1, 64+ sin(aa-1.5)*str*0.1, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки
    a=a+PI/30;
    for (float i = 0.01; i < 2 * PI; i = i + PI / 30) {
     tft.drawLine(80 + cos(i)*str * 0.9,  64 + sin(i)*str * 0.9, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_GREEN    ); // риски-метки шкалы через 1 сек 
     }
    for (float i = 0.01; i < 2 * PI; i = i + PI / 6) {
     tft.drawLine(80 + cos(i)*str * 0.75,  64 + sin(i)*str * 0.75, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_WHITE   ); // риски-метки шкалы через 5 сек 
     }
   // tft.drawLine(80, 64, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE ); // рисование новой стрелки-отрезка
    tft.drawLine(80+ cos(a+1.5)*str*0.1, 64+ sin(a+1.5)*str*0.1, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE );// рисование новой стрелки
    tft.drawLine(80+ cos(a-1.5)*str*0.1, 64+ sin(a-1.5)*str*0.1, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE );// рисование новой стрелки
 //   
  tft.drawCircle(80,64,5,ST7735_WHITE );
  tft.drawCircle(80,64,4,ST7735_WHITE );
  tft.setCursor(50, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.println(utf8rus("СЕКУНДОМЕР"));
  tft.setCursor(70, 80);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
 if(sek<10){tft.print("0");}tft.println(sek);
  sek++;if(sek>59){sek=0;}
  //
 delay(835);//подбираем опытным путём
  tft.fillRect(70, 80, 30, 20, ST7735_BLACK);
}
////////////////////////////////////////////////////////////////////////
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
///////////////////////////////////////////////////////////////////////////

Секундомер.

 

lilik
Offline
Зарегистрирован: 19.10.2017

С ч\б картинками разобрался, осталось научится их раскрашивать в разные цвета, имея одноцветный массив. Наверное из библиотеки функцию изымать и выдумывать зависимости цвета от счётчиков пикселей - i, j :)

секундомера стрелку (некстати) сделал накладывающейся - как настоящая.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Код секундомера для RP2040, русских шрифтов нет, увы...

// СЕКУНДОМЕР
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

#define SPI01 // Дисплей на SPI1, NRF24L01 на SPI0

#if defined(SPI01)        // для RP2040 SPI1
#define TFT_CS        13  // GP13 - CS
#define TFT_RST       14  // GP14 - RESET
#define TFT_DC        15  // GP15 - A0
#define TFT_MISO      12  // GP12 - MISO (MISO, RX)
#define TFT_MOSI      11  // GP11 - SDA  (MOSI, TX)
#define TFT_SCLK      10  // GP10 - SCK

#else                       // для RP2040 SPI0
#define TFT_CS        5   // GP5 - CS
#define TFT_RST       6   // GP6 - RESET
#define TFT_DC        7   // GP7 - A0
#define TFT_MISO      4   // GP4 - MISO (MISO, RX)
#define TFT_MOSI      3   // GP3 - SDA  (MOSI, TX)
#define TFT_SCLK      2   // GP2 - SCK
#endif

// For ST7735-based displays, we will use this call
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

float a = 0.00; // переменная для угла поворота стрелки
float aa = 0.00; // переменная для угла поворота стрелки (предыдущее значение)
int str = 55; //длина стрелки в пикселях
byte sek=16;//

void setup(void) {
  // Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(1);//ориентация экрана
 tft.setSPISpeed(50000000);
 tft.drawCircle(80,64,63,ST7735_WHITE );//обод секундомера
 tft.drawCircle(80,64,62,ST7735_WHITE );
 tft.drawCircle(80,64,61,ST7735_WHITE );
  
}
void loop() {
 // 
 aa = a;  
   // tft.drawLine(80, 64, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки-отрезка
   tft.drawLine(80+ cos(aa+1.5)*str*0.1, 64+ sin(aa+1.5)*str*0.1, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки
   tft.drawLine(80+ cos(aa-1.5)*str*0.1, 64+ sin(aa-1.5)*str*0.1, 80 + cos(aa)*str, 64 + sin(aa)*str,ST7735_BLACK ); // стирание старой стрелки
    a=a+PI/30;
    for (float i = 0.01; i < 2 * PI; i = i + PI / 30) {
     tft.drawLine(80 + cos(i)*str * 0.9,  64 + sin(i)*str * 0.9, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_GREEN    ); // риски-метки шкалы через 1 сек 
     }
    for (float i = 0.01; i < 2 * PI; i = i + PI / 6) {
     tft.drawLine(80 + cos(i)*str * 0.75,  64 + sin(i)*str * 0.75, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_WHITE   ); // риски-метки шкалы через 5 сек 
     }
   // tft.drawLine(80, 64, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE ); // рисование новой стрелки-отрезка
    tft.drawLine(80+ cos(a+1.5)*str*0.1, 64+ sin(a+1.5)*str*0.1, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE );// рисование новой стрелки
    tft.drawLine(80+ cos(a-1.5)*str*0.1, 64+ sin(a-1.5)*str*0.1, 80 + cos(a)*str, 64 + sin(a)*str,ST7735_WHITE );// рисование новой стрелки
 //   
  tft.drawCircle(80,64,5,ST7735_WHITE );
  tft.drawCircle(80,64,4,ST7735_WHITE );
  tft.setCursor(50, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.println(utf8rus("СЕКУНДОМЕР"));
  tft.setCursor(70, 80);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
 if(sek<10){tft.print("0");}tft.println(sek);
  sek++;if(sek>59){sek=0;}
  //
 delay(835);//подбираем опытным путём
  tft.fillRect(70, 80, 30, 20, ST7735_BLACK);
}
////////////////////////////////////////////////////////////////////////
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
///////////////////////////////////////////////////////////////////////////

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А почему такая медленная перерисовка?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

А почему такая медленная перерисовка?

пока не знаю, скорость на SPI выставлена по максимуму

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

Код секундомера для RP2040, русских шрифтов нет, увы...


А картинка?

Я по ходу забыл, в файлы библиотеки "...GFX" надо добавить

#ifndef FONT5X7_H
#define FONT5X7_H

#ifdef __AVR__
 #include <avr/io.h>
 #include <avr/pgmspace.h>
#elif defined(ESP8266)
 #include <pgmspace.h>
#else
 #define PROGMEM
#endif

// Standard ASCII 5x7 font

static const unsigned char font[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x55, 0x51, 0x55, 0x3E, 
0x3E, 0x6B, 0x6F, 0x6B, 0x3E, 
0x0C, 0x1E, 0x3C, 0x1E, 0x0C, 
0x08, 0x1C, 0x3E, 0x1C, 0x08, 
0x1C, 0x4A, 0x7F, 0x4A, 0x1C, 
0x18, 0x5C, 0x7F, 0x5C, 0x18, 
0x00, 0x1C, 0x1C, 0x1C, 0x00, 
0x7F, 0x63, 0x63, 0x63, 0x7F, 
0x00, 0x1C, 0x14, 0x1C, 0x00, 
0x7F, 0x63, 0x6B, 0x63, 0x7F, 
0x30, 0x48, 0x4D, 0x33, 0x07, 
0x06, 0x29, 0x79, 0x29, 0x06, 
0x20, 0x50, 0x3F, 0x02, 0x0C, 
0x60, 0x7F, 0x05, 0x35, 0x3F, 
0x2A, 0x1C, 0x77, 0x1C, 0x2A, 
0x00, 0x7F, 0x3E, 0x1C, 0x08, 
0x08, 0x1C, 0x3E, 0x7F, 0x00, 
0x14, 0x22, 0x7F, 0x22, 0x14, 
0x00, 0x5F, 0x00, 0x5F, 0x00, 
0x06, 0x09, 0x7F, 0x01, 0x7F, 
0x4A, 0x55, 0x55, 0x55, 0x29, 
0x60, 0x60, 0x60, 0x60, 0x60, 
0x54, 0x62, 0x7F, 0x62, 0x54, 
0x08, 0x04, 0x7E, 0x04, 0x08, 
0x08, 0x10, 0x3F, 0x10, 0x08, 
0x08, 0x08, 0x2A, 0x1C, 0x08, 
0x08, 0x1C, 0x2A, 0x08, 0x08, 
0x1C, 0x10, 0x10, 0x10, 0x10, 
0x1C, 0x3E, 0x08, 0x3E, 0x1C, 
0x30, 0x3C, 0x3F, 0x3C, 0x30, 
0x06, 0x1E, 0x7E, 0x1E, 0x06, 
0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x5F, 0x00, 0x00, 
0x00, 0x07, 0x00, 0x07, 0x00, 
0x14, 0x7F, 0x14, 0x7F, 0x14, 
0x24, 0x2A, 0x7F, 0x2A, 0x12, 
0x23, 0x13, 0x08, 0x64, 0x62, 
0x36, 0x49, 0x56, 0x20, 0x50, 
0x00, 0x00, 0x07, 0x00, 0x00, 
0x00, 0x1C, 0x22, 0x41, 0x00, 
0x00, 0x41, 0x22, 0x1C, 0x00, 
0x14, 0x08, 0x3E, 0x08, 0x14, 
0x08, 0x08, 0x3E, 0x08, 0x08, 
0x00, 0xA0, 0x60, 0x00, 0x00, 
0x08, 0x08, 0x08, 0x08, 0x08, 
0x00, 0x60, 0x60, 0x00, 0x00, 
0x20, 0x10, 0x08, 0x04, 0x02, 
0x3E, 0x51, 0x49, 0x45, 0x3E, 
0x44, 0x42, 0x7F, 0x40, 0x40, 
0x42, 0x61, 0x51, 0x49, 0x46, 
0x21, 0x41, 0x45, 0x4B, 0x31, 
0x18, 0x14, 0x12, 0x7F, 0x10, 
0x27, 0x45, 0x45, 0x45, 0x39, 
0x3C, 0x4A, 0x49, 0x49, 0x30, 
0x01, 0x71, 0x09, 0x05, 0x03, 
0x36, 0x49, 0x49, 0x49, 0x36, 
0x06, 0x49, 0x49, 0x29, 0x1E, 
0x00, 0x6C, 0x6C, 0x00, 0x00, 
0x00, 0xAC, 0x6C, 0x00, 0x00, 
0x08, 0x14, 0x22, 0x41, 0x00, 
0x14, 0x14, 0x14, 0x14, 0x14, 
0x00, 0x41, 0x22, 0x14, 0x08, 
0x02, 0x01, 0x51, 0x09, 0x06, 
0x3E, 0x41, 0x5D, 0x55, 0x5E, 
0x7C, 0x12, 0x11, 0x12, 0x7C, 
0x7F, 0x49, 0x49, 0x49, 0x36, 
0x3E, 0x41, 0x41, 0x41, 0x22, 
0x7F, 0x41, 0x41, 0x22, 0x1C, 
0x7F, 0x49, 0x49, 0x49, 0x41, 
0x7F, 0x09, 0x09, 0x09, 0x01, 
0x3E, 0x41, 0x49, 0x49, 0x7A, 
0x7F, 0x08, 0x08, 0x08, 0x7F, 
0x00, 0x41, 0x7F, 0x41, 0x00, 
0x20, 0x40, 0x41, 0x3F, 0x01, 
0x7F, 0x08, 0x14, 0x22, 0x41, 
0x7F, 0x40, 0x40, 0x40, 0x60, 
0x7F, 0x02, 0x0C, 0x02, 0x7F, 
0x7F, 0x04, 0x08, 0x10, 0x7F, 
0x3E, 0x41, 0x41, 0x41, 0x3E, 
0x7F, 0x09, 0x09, 0x09, 0x06, 
0x3E, 0x41, 0x51, 0x21, 0x5E, 
0x7F, 0x09, 0x19, 0x29, 0x46, 
0x46, 0x49, 0x49, 0x49, 0x31, 
0x03, 0x01, 0x7F, 0x01, 0x03, 
0x3F, 0x40, 0x40, 0x40, 0x3F, 
0x1F, 0x20, 0x40, 0x20, 0x1F, 
0x3F, 0x40, 0x3C, 0x40, 0x3F, 
0x63, 0x14, 0x08, 0x14, 0x63, 
0x07, 0x08, 0x70, 0x08, 0x07, 
0x61, 0x51, 0x49, 0x45, 0x43, 
0x00, 0x7F, 0x41, 0x41, 0x00, 
0x02, 0x04, 0x08, 0x10, 0x20, 
0x00, 0x41, 0x41, 0x7F, 0x00, 
0x04, 0x02, 0x01, 0x02, 0x04, 
0x40, 0x40, 0x40, 0x40, 0x40, 
0x00, 0x01, 0x02, 0x04, 0x00, 
0x20, 0x54, 0x54, 0x54, 0x78, 
0x7F, 0x48, 0x44, 0x44, 0x38, 
0x38, 0x44, 0x44, 0x44, 0x48, 
0x38, 0x44, 0x44, 0x48, 0x7F, 
0x38, 0x54, 0x54, 0x54, 0x18, 
0x08, 0x7E, 0x09, 0x01, 0x02, 
0x08, 0x54, 0x54, 0x58, 0x3C, 
0x7F, 0x08, 0x04, 0x04, 0x78, 
0x00, 0x44, 0x7D, 0x40, 0x00, 
0x20, 0x40, 0x44, 0x3D, 0x00, 
0x7F, 0x10, 0x10, 0x28, 0x44, 
0x00, 0x41, 0x7F, 0x40, 0x00, 
0x7C, 0x04, 0x78, 0x04, 0x78, 
0x7C, 0x08, 0x04, 0x04, 0x78, 
0x38, 0x44, 0x44, 0x44, 0x38, 
0x7C, 0x14, 0x14, 0x14, 0x08, 
0x08, 0x14, 0x14, 0x0C, 0x7C, 
0x7C, 0x08, 0x04, 0x04, 0x08, 
0x48, 0x54, 0x54, 0x54, 0x24, 
0x04, 0x3F, 0x44, 0x40, 0x20, 
0x3C, 0x40, 0x40, 0x20, 0x7C, 
0x1C, 0x20, 0x40, 0x20, 0x1C, 
0x3C, 0x40, 0x38, 0x40, 0x3C, 
0x44, 0x28, 0x10, 0x28, 0x44, 
0x0C, 0x50, 0x50, 0x50, 0x3C, 
0x44, 0x64, 0x54, 0x4C, 0x44, 
0x00, 0x08, 0x36, 0x41, 0x00, 
0x00, 0x00, 0x7F, 0x00, 0x00, 
0x00, 0x41, 0x36, 0x08, 0x00, 
0x02, 0x01, 0x02, 0x04, 0x02, 
0x70, 0x48, 0x44, 0x48, 0x70, 
0x00, 0x0E, 0x11, 0x0E, 0x00, 
0x00, 0x12, 0x1F, 0x10, 0x00, 
0x00, 0x12, 0x19, 0x16, 0x00, 
0x00, 0x11, 0x15, 0x0B, 0x00, 
0x00, 0x07, 0x04, 0x1F, 0x00, 
0x00, 0x17, 0x15, 0x09, 0x00, 
0x00, 0x0E, 0x15, 0x09, 0x00, 
0x00, 0x01, 0x1D, 0x03, 0x00, 
0x00, 0x0A, 0x15, 0x0A, 0x00, 
0x00, 0x12, 0x15, 0x0E, 0x00, 
0x00, 0x04, 0x04, 0x04, 0x00, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0x3E, 0x00, 0x00, 0x00, 0x00, 
0x3E, 0x3E, 0x00, 0x00, 0x00, 
0x3E, 0x3E, 0x00, 0x3E, 0x00, 
0x3E, 0x3E, 0x00, 0x3E, 0x3E, 
0x80, 0x80, 0x80, 0x80, 0x80, 
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 
0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 
0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 
0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 
0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 
0x40, 0x00, 0x40, 0x00, 0x40, 
0x60, 0x00, 0x40, 0x00, 0x40, 
0x60, 0x00, 0x70, 0x00, 0x40, 
0x60, 0x00, 0x70, 0x00, 0x78, 
0x7C, 0x00, 0x40, 0x00, 0x40, 
0x7C, 0x00, 0x7E, 0x00, 0x40, 
0x7C, 0x00, 0x7E, 0x00, 0x7F, 
0x1C, 0x77, 0x41, 0x41, 0x41, 
0x41, 0x41, 0x41, 0x41, 0x41, 
0x41, 0x41, 0x41, 0x7F, 0x00, 
0x1C, 0x77, 0x41, 0x5D, 0x5D, 
0x41, 0x41, 0x41, 0x5D, 0x5D, 
0x5D, 0x5D, 0x41, 0x5D, 0x5D, 
0x5D, 0x5D, 0x41, 0x7F, 0x00, 
0x22, 0x1C, 0x14, 0x1C, 0x22, 
0x00, 0x08, 0x1C, 0x08, 0x00, 
0x00, 0x00, 0x77, 0x00, 0x00, 
0x46, 0x5D, 0x55, 0x5D, 0x31, 
0x7C, 0x55, 0x54, 0x55, 0x44, 
0x08, 0x08, 0x2A, 0x08, 0x08, 
0x00, 0x14, 0x08, 0x14, 0x00, 
0x08, 0x14, 0x22, 0x08, 0x14, 
0x7F, 0x41, 0x71, 0x31, 0x1F, 
0x03, 0x05, 0x7F, 0x05, 0x03, 
0x22, 0x14, 0x7F, 0x55, 0x22, 
0x02, 0x55, 0x7D, 0x05, 0x02, 
0x06, 0x09, 0x09, 0x06, 0x00, 
0x44, 0x44, 0x5F, 0x44, 0x44, 
0x1C, 0x14, 0x1C, 0x22, 0x7F, 
0x20, 0x3E, 0x61, 0x3E, 0x20, 
0x20, 0x50, 0x3F, 0x02, 0x0C, 
0x80, 0x7C, 0x20, 0x3C, 0x40, 
0x44, 0x3C, 0x04, 0x7C, 0x44, 
0x00, 0x00, 0x08, 0x00, 0x00, 
0x38, 0x55, 0x54, 0x55, 0x18, 
0x7E, 0x08, 0x10, 0x7F, 0x01, 
0x08, 0x10, 0x08, 0x04, 0x02, 
0x14, 0x08, 0x22, 0x14, 0x08, 
0x0E, 0x06, 0x0A, 0x10, 0x20, 
0x20, 0x10, 0x0A, 0x06, 0x0E, 
0x00, 0x00, 0x00, 0x00, 0x00,
0x38, 0x30, 0x28, 0x04, 0x02, 
0x02, 0x04, 0x28, 0x30, 0x38, 
0x7E, 0x11, 0x11, 0x11, 0x7E, 
0x7F, 0x49, 0x49, 0x49, 0x31, 
0x7F, 0x49, 0x49, 0x49, 0x36, 
0x7F, 0x01, 0x01, 0x01, 0x03, 
0xC0, 0x7F, 0x41, 0x7F, 0xC0, 
0x7F, 0x49, 0x49, 0x49, 0x41, 
0x77, 0x08, 0x7F, 0x08, 0x77, 
0x41, 0x49, 0x49, 0x49, 0x36, 
0x7F, 0x10, 0x08, 0x04, 0x7F, 
0x7C, 0x21, 0x12, 0x09, 0x7C, 
0x7F, 0x08, 0x14, 0x22, 0x41, 
0x40, 0x3E, 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, 0x3F, 
0x0E, 0x11, 0x7F, 0x11, 0x0E, 
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, 0x30, 
0x7F, 0x48, 0x48, 0x30, 0x7F, 
0x7F, 0x48, 0x48, 0x48, 0x30, 
0x22, 0x41, 0x49, 0x49, 0x3E, 
0x7F, 0x08, 0x3E, 0x41, 0x3E, 
0x46, 0x29, 0x19, 0x09, 0x7F, 
0x20, 0x54, 0x54, 0x54, 0x78, 
0x3C, 0x4A, 0x4A, 0x49, 0x31, 
0x7C, 0x54, 0x54, 0x54, 0x28, 
0x7C, 0x04, 0x04, 0x04, 0x0C, 
0xC0, 0x78, 0x44, 0x7C, 0xC0, 
0x38, 0x54, 0x54, 0x54, 0x18, 
0x6C, 0x10, 0x7C, 0x10, 0x6C, 
0x44, 0x54, 0x54, 0x54, 0x28, 
0x7C, 0x20, 0x10, 0x08, 0x7C, 
0x7C, 0x40, 0x26, 0x10, 0x7C, 
0x7C, 0x10, 0x10, 0x28, 0x44, 
0x40, 0x38, 0x04, 0x04, 0x7C, 
0x7C, 0x08, 0x10, 0x08, 0x7C, 
0x7C, 0x10, 0x10, 0x10, 0x7C, 
0x38, 0x44, 0x44, 0x44, 0x38, 
0x7C, 0x04, 0x04, 0x04, 0x7C, 
0x7C, 0x14, 0x14, 0x14, 0x08, 
0x38, 0x44, 0x44, 0x44, 0x48, 
0x04, 0x04, 0x7C, 0x04, 0x04, 
0x0C, 0x50, 0x50, 0x50, 0x3C, 
0x18, 0x24, 0xFC, 0x24, 0x18, 
0x44, 0x28, 0x10, 0x28, 0x44, 
0x7C, 0x40, 0x40, 0x7C, 0xC0, 
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, 0x50, 0x20, 
0x28, 0x44, 0x54, 0x54, 0x38, 
0x7C, 0x10, 0x38, 0x44, 0x38, 
0x48, 0x34, 0x14, 0x14, 0x7C};
#endif // FONT5X7_H

 

lilik
Offline
Зарегистрирован: 19.10.2017

glcdfont.c файл называется.

Новая версия, ещё более тормознутая отрисовка стрелки.

// СЕКУНДОМЕР
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9  
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

float a = 0.00; // переменная для угла поворота стрелки
float aa = 0.00; // переменная для угла поворота стрелки (предыдущее значение)
int str = 55; //длина стрелки в пикселях
byte sek=16;//

void setup(void) {
  // Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(1);//ориентация экрана
 tft.drawCircle(80,64,63,ST7735_WHITE );//обод секундомера
 tft.drawCircle(80,64,62,ST7735_WHITE );
 tft.drawCircle(80,64,61,ST7735_WHITE );
  
}
void loop() {
 // 
 aa = a;
 //
  tft.setCursor(50, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.println(utf8rus("СЕКУНДОМЕР"));
  tft.setCursor(70, 80);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
 if(sek<10){tft.print("0");}tft.println(sek);
 //  
  tft.fillTriangle(80+ cos(aa+1.5)*str*0.1, 64+ sin(aa+1.5)*str*0.1, 80 + cos(aa)*str, 64 + sin(aa)*str,80+ cos(aa-1.5)*str*0.1, 64+ sin(aa-1.5)*str*0.1,ST7735_BLACK );// стирание старой стрелки 
   a=a+PI/30;
    tft.fillCircle(80,64,7,ST7735_WHITE );
    for (float i = 0.01; i < 2 * PI; i = i + PI / 30) {
     tft.drawLine(80 + cos(i)*str * 0.90,  64 + sin(i)*str * 0.90, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_GREEN    ); // риски-метки шкалы через 1 сек 
     }
    for (float i = 0.01; i < 2 * PI; i = i + PI / 6) {
     tft.drawLine(80 + cos(i)*str * 0.75,  64 + sin(i)*str * 0.75, 80 + cos(i)*str,  64 + sin(i)*str,ST7735_WHITE   ); // риски-метки шкалы через 5 сек 
     }
    tft.fillTriangle(80+ cos(a+1.5)*str*0.1, 64+ sin(a+1.5)*str*0.1, 80 + cos(a)*str, 64 + sin(a)*str,80+ cos(a-1.5)*str*0.1, 64+ sin(a-1.5)*str*0.1,ST7735_WHITE );// рисование новой стрелки
  tft.fillCircle(80,64,3,ST7735_BLACK );
     
  sek++;if(sek>59){sek=0;}
  //
 delay(835);//подбираем опытным путём
  tft.fillRect(70, 80, 30, 20, ST7735_BLACK);
}
////////////////////////////////////////////////////////////////////////
/* Функция перекодировки русских букв из UTF-8 в Win-1251 */
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
///////////////////////////////////////////////////////////////////////////

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

andriano пишет:

А почему такая медленная перерисовка?

пока не знаю, скорость на SPI выставлена по максимуму

Максимум - это сколько? 4MHz?

Давай считать: Для одного пикселя нужно записать 16 бит, что при 4МГц будет 4 мкс, что соответствует 64 тактам при 16 МГц. Ну еще преобразование 1 бита 16 - это 8-10 инструкций, пусть будет еще 16 тактов. Итого 80 тактов или 5 мкс.

На экране 160*128=20к пикселей, по 5 мкс на каждый - 100 мс. Т.е. должно быть порядка 10 fps. Мы видим явно меньше, вопрос - почему?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

andriano он же через библиотеку выводит ... - дели скорость на 100 :-)

Не 10 кадров в секунду, а 10 секунда на кадр ...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Komandir пишет:

andriano он же через библиотеку выводит ... - дели скорость на 100 :-)

Не 10 кадров в секунду, а 10 секунда на кадр ...

Ну да...

Вот поэтому я никогда и не пользуюсь стандартными библиотеками для экрана, а предпочитаю писать сам.

lilik, покажи тот фрагмент, который выводит на экран первый рисунок из сообщения №25.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

lilik На какой частоте работает плата ? Если на 16, то fosc/2 - это 8, а не 4 ...

Жаль что нет буфера как на UART - ожидание окончания вывода даёт паузы между байтами ...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Спасибо! Вторая половина кодовой таблицы с выбором языка оказывается только ручками  )))
Что-то я на этом тормознулся, хотя с DOS был жеж более чем в теме... Осень...
Да, я добавил в ваш код установку скорости SPI, отрабатывает ли должным образом
надо разбираться, но если ставить скорость 60000000 то дисплей не АЛЛЁ )))
 

  tft.setSPISpeed(50000000);

 

lilik
Offline
Зарегистрирован: 19.10.2017

andriano пишет:

lilik, покажи тот фрагмент, который выводит на экран первый рисунок из сообщения №25.

// РИСУНОК
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9  
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
extern const unsigned char ris_1[];
extern const unsigned char ris_2[];

void setup(void) {
// Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(0);//ориентация экрана
 }
void loop() {
 tft.drawBitmap(0,0,ris_1, 128,160,tft.Color565(255,255,255),0);
 tft.drawBitmap(0,0,ris_2, 128,160,tft.Color565(255,255,255),0);
 }

 

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

Да, я добавил в ваш код установку скорости SPI, отрабатывает ли должным образом...

 

  tft.setSPISpeed(50000000);

 

Скетч не компилируется.

lilik
Offline
Зарегистрирован: 19.10.2017

Komandir пишет:

lilik На какой частоте работает плата ? Если на 16, то fosc/2 - это 8, а не 4 ...

Жаль что нет буфера как на UART - ожидание окончания вывода даёт паузы между байтами ...

Плата UNO китайская с CH340.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

50 МГц ??? У вас Uno, а не RP2040 !!!

lilik
Offline
Зарегистрирован: 19.10.2017

Komandir пишет:

50 МГц ??? У вас Uno, а не RP2040 !!!

Да!, но не компилируется не из-за чисел :)

Вот так компилируется и работает, но число 16000000 (и любые другие) ни на что не влияют.

// РИСУНОК
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9  
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
extern const unsigned char ris_1[];
extern const unsigned char ris_2[];

void setup(void) {
  // Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(0);//ориентация экрана
 SPI.begin();
 SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
 }
void loop() {
 tft.drawBitmap(0,0,ris_1, 128,160,tft.Color565(255,255,255),0);
 tft.drawBitmap(0,0,ris_2, 128,160,tft.Color565(255,255,255),0);
 }

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lilik пишет:

andriano пишет:

lilik, покажи тот фрагмент, который выводит на экран первый рисунок из сообщения №25.

 tft.drawBitmap(0,0,ris_1, 128,160,tft.Color565(255,255,255),0);
 tft.drawBitmap(0,0,ris_2, 128,160,tft.Color565(255,255,255),0);
 }

 

Вообще-то под "фрагмент, который выводит" я подразумевал немножко иное...

Ну а раз так - сообщения №32-33.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

На UNO 16 МНц частота SPI не может быть выше 8 МНц

SPI.setClockDivider(SPI_CLOCK_DIV2);

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну и кроме того, по моим наблюдениям, 8МГц на AVR практически не отличается от 4МГц.

Да и вообще, с реализацией SPI на Arduino нужно как следует разбираться: если для AVR я установил лишь факт, описанный выше (т.е. относительное значение), то для stm32 получил абсолютное: на практике скорость передачи 1/7 от теоретического значения.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

Ну и кроме того, по моим наблюдениям, 8МГц на AVR практически не отличается от 4МГц.

Да и вообще, с реализацией SPI на Arduino нужно как следует разбираться: если для AVR я установил лишь факт, описанный выше (т.е. относительное значение), то для stm32 получил абсолютное: на практике скорость передачи 1/7 от теоретического значения.

  а как померить реальную скорость?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Есть такая функция - millis().

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

lilik
Offline
Зарегистрирован: 19.10.2017

Komandir пишет:

На UNO 16 МНц частота SPI не может быть выше 8 МНц

SPI.setClockDivider(SPI_CLOCK_DIV2);

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

// РИСУНОК
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9  
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
extern const unsigned char ris_1[];
extern const unsigned char ris_2[];

void setup(void) {
  // Используйте этот инициализатор, если вы используете 1,8-дюймовый TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
 tft.fillScreen(ST7735_BLACK);
 tft.setRotation(0);//ориентация экрана
 }
void loop() {
 
drawBitmap_(0,0,ris_1, 128,160);
  delay(200);//
}
////////////////////////////////////////////////////////
void drawBitmap_(int16_t x, int16_t y,
 const uint8_t *bitmap, int16_t w, int16_t h) {
 int16_t i, j, byteWidth = (w + 7) / 8;
  uint8_t byte;

  for(j=0; j<h; j++) {
    for(i=0; i<w; i++) {
      if(i & 7) byte <<= 1;
      else      byte   = pgm_read_byte(bitmap + j * byteWidth + i / 8);
      if(byte & 0x80)
      {
      //tft.drawPixel(x+i, y+j,tft.Color565(255,255,255) );
        if(j>h/2-5&&i<=w/2-5){tft.drawPixel(x+i, y+j,tft.Color565(0,255,0) );}
        if(j<=h/2-5&&i>w/2-5){tft.drawPixel(x+i, y+j,tft.Color565(255,0,255) );}
        if(j>h/2-5&&i>w/2-5){tft.drawPixel(x+i, y+j,tft.Color565(0,150,255) );}
        if(i*i+j*j<10010&&j<=w){tft.drawPixel(x+i, y+j,tft.Color565(255,0,0) );}
       }
    }
  }
}
//////////////////////////////////////////////////////////

  Она переделывает одну картинку в другую.

Может дело в попиксельном выводе данных?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

пока вы не переделаете вывод пикселей картинки напрямую дисплею в память, скорости нормальной не получите.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Да, выводить попиксельно - это неправильно.

В контроллерах цветных дисплеев (во всех, с которыми мне приходилось работать) специально для увеличения скорости вывода пикселей используется функция, задающая прямоугольник, в который осуществляется вывод. Например, для вывода символа в знакоместо 10*16 задается прямоугольная область такого размера, а потом просто поочередно передаются цвета точек, которые последовательно заполняют эту область. 

Т.е. на вывод 160 точек в примере выше мы сначала задаем команду 6-16 байт, а потом цвета всех 160 точек, т.е. еще 320 байт. Т.е. из примерно 330 байт 320 передают информацию о цвете точек.

При попиксельном выводе все то же самое, только на 3-16 байт служебной информации (задающей координаты точки) приходится только 2 байта на цвет (единственной точки).

В случае картинки и невозможности уместить ее в памяти целиком, целесообразно выводить построчно: т.е. задали строку 128*1 пискель, посчитали в буфер (256 байт) и вывели на экран. Потом - следующую.

lilik
Offline
Зарегистрирован: 19.10.2017

andycat пишет:

пока вы не переделаете вывод пикселей картинки напрямую дисплею в память, скорости нормальной не получите.

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

void Adafruit_ST7735::drawPixel(int16_t x, int16_t y, uint16_t color) 
{

  if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;

  setAddrWindow(x,y,x+1,y+1);

#if defined (SPI_HAS_TRANSACTION)
  if (hwSPI)     SPI.beginTransaction(mySPISettings);
#endif

  DC_HIGH();
  CS_LOW();
  spiwrite(color >> 8);
  spiwrite(color);
  CS_HIGH();

#if defined (SPI_HAS_TRANSACTION)
  if (hwSPI)     SPI.endTransaction();
#endif
}

 

void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) {
  // Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
  static const uint8_t PROGMEM
    GFXsetBit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 },
    GFXclrBit[] = { 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE };

  if(buffer) {
    if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;

    int16_t t;
    switch(rotation) {
     case 1:
      t = x;
      x = WIDTH  - 1 - y;
      y = t;
      break;
     case 2:
      x = WIDTH  - 1 - x;
      y = HEIGHT - 1 - y;
      break;
     case 3:
      t = x;
      x = y;
      y = HEIGHT - 1 - t;
      break;
    }

Кстати такой блок нашёл, он на скорость влиет?

inline void Adafruit_ST7735::CS_HIGH(void) 
{
#if defined(USE_FAST_IO)
  *csport |= cspinmask;
#else
  digitalWrite(_cs, HIGH);
#endif
}

inline void Adafruit_ST7735::CS_LOW(void) 
{
#if defined(USE_FAST_IO)
  *csport &= ~cspinmask;
#else
  digitalWrite(_cs, LOW);
#endif
}

inline void Adafruit_ST7735::DC_HIGH(void) 
{
#if defined(USE_FAST_IO)
  *dcport |= dcpinmask;
#else
  digitalWrite(_dc, HIGH);
#endif
}

inline void Adafruit_ST7735::DC_LOW(void) 
{
#if defined(USE_FAST_IO)
  *dcport &= ~dcpinmask;
#else
  digitalWrite(_dc, LOW);
#endif
}

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

lilik пишет:

andycat пишет:

пока вы не переделаете вывод пикселей картинки напрямую дисплею в память, скорости нормальной не получите.

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

void Adafruit_ST7735::drawPixel(int16_t x, int16_t y, uint16_t color) 
{

  if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;

  setAddrWindow(x,y,x+1,y+1);

#if defined (SPI_HAS_TRANSACTION)
  if (hwSPI)     SPI.beginTransaction(mySPISettings);
#endif

  DC_HIGH();
  CS_LOW();
  spiwrite(color >> 8);
  spiwrite(color);
  CS_HIGH();

#if defined (SPI_HAS_TRANSACTION)
  if (hwSPI)     SPI.endTransaction();
#endif
}

 

 

ну вот же она, задается координаты вывода, как выше писали. Формируете буфер данных для вывода, и по SPI шлете все это дисплею.

вот из проекта для ili9341, суть та же. (только это для STM + DMA)

void f3spitft::tftSetAddrWindow(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1) {
	static unsigned char pos_data[4];
	// column address set
	tftSendCommand(0x2A); // CASET
	while (this->spiBUSY());
	pos_data[0] = (x0 >> 8) & 0xFF;
	pos_data[1] = x0 & 0xFF;
	pos_data[2] = (x1 >> 8) & 0xFF;
	pos_data[3] = x1 & 0xFF;
	tftWriteData((unsigned char *)&pos_data, 4);
	while (this->spiBUSY());
	// row address set
	tftSendCommand(0x2B); // RASET
	while (this->spiBUSY());
	pos_data[0] = (y0 >> 8) & 0xFF;
	pos_data[1] = y0 & 0xFF;
	pos_data[2] = (y1 >> 8) & 0xFF;
	pos_data[3] = y1 & 0xFF;
	tftWriteData((unsigned char *)&pos_data, 4);
	while (this->spiBUSY());
	// write to RAM
	tftSendCommand(0x2C); // RAMWR
	while (this->spiBUSY());
}

void f3spitft::tftPrintBuffer(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned char * inData) {
	  if((x1 >= tftWIDTH) || (y1 >= tftHEIGHT) || (x2 >= tftWIDTH) || (y2 >= tftHEIGHT)) return;
	  if((x1 >= tftWIDTH) || (y1 >= tftHEIGHT) || (x2 >= tftWIDTH) || (y2 >= tftHEIGHT)) return;
	  if(x1>x2) swap(x1,x2);
	  if(y1>y2) swap(y1,y2);
	unsigned short sizeData = (x2-x1+1)*(y2-y1+1);
	  tftSetAddrWindow(x1, y1, x2, y2);
	  tftSetPinDC(1);
	tftSetPinCS(0); // говорим slave устройству что начинаем работать
	inWork = 1; // флаг начала работы
	DMA1_Channel3->CCR &= ~DMA_CCR_EN; // отключаем любое действие канала если идет передача
	DMA1_Channel3->CPAR = (unsigned long)(&SPI1->DR); //заносим адрес регистра DR в CPAR
	DMA1_Channel3->CMAR = (unsigned long)(unsigned char *)inData; //заносим адрес данных в регистр CMAR
	DMA1_Channel3->CNDTR = sizeData; //количество передаваемых данных // 16 битных слов, т е пикселей
	DMA1_Channel3->CCR &= ~DMA_CCR_MEM2MEM; //режим MEM2MEM отключен
	DMA1_Channel3->CCR &= ~DMA_CCR_PL; //приоритет низкий
	DMA1_Channel3->CCR &= ~DMA_CCR_MSIZE; //разрядность данных в памяти 16 бит // 01: 16-bits
	DMA1_Channel3->CCR |= DMA_CCR_MSIZE_0; //разрядность данных в памяти 16 бит // 01: 16-bits
	DMA1_Channel3->CCR &= ~DMA_CCR_PSIZE; //разрядность регистра данных 16 бит в шину SPI
	DMA1_Channel3->CCR |= DMA_CCR_PSIZE_0; //разрядность регистра данных 16 бит в шину SPI
	DMA1_Channel3->CCR |= DMA_CCR_MINC; // включить инкремент адреса памяти
	DMA1_Channel3->CCR &= ~DMA_CCR_PINC; //Инкремент адреса периферии отключен
	DMA1_Channel3->CCR &= ~DMA_CCR_CIRC; //кольцевой режим отключен
	DMA1_Channel3->CCR |= DMA_CCR_DIR; //1 - из памяти в периферию
	SPI1->CR2 |= SPI_CR2_TXDMAEN; // разрешить отправку через DMA
	DMA1_Channel3->CCR |= DMA_CCR_EN; // включаем передачу данных
}

void f3spitft::tftShowBackground(unsigned char * inPic) { // выводим фоновую карптинку двумя частями в половину экрана
	tftPrintBuffer(0, 0, tftWIDTH-1, tftHEIGHT/2-1, inPic);
	while (this->spiBUSY());
	tftPrintBuffer(0, tftHEIGHT/2, tftWIDTH-1, tftHEIGHT-1, inPic+tftWIDTH*tftHEIGHT);
	while (this->spiBUSY());
}