Имитация различных шкал на дисплее 128*64

b707
Offline
Зарегистрирован: 26.05.2017

lilik - не надо пытаться осчастливить всех, предлагая некий усредненный вариант. Так недолго и до общих в колхозе баб :)

Красота - она в разнообразии, а не в стандартизации.

Logik
Offline
Зарегистрирован: 05.08.2014

Это точно. Я потому в либку векторных шрифтов передаю указател на функцию прорисовки отрезка. Это посути все, что нужно от графических возможностей экрана.  Получаю поток вызовов с координатами, а уже в своей этой функции делаю разнообразие, если надо. Наклоны, курсив, извраты всякие, типа  https://www.youtube.com/watch?v=Omc9WdDXeWE просто пересчетом этих самых координат. Болд - несколько линий вместо одной с смещениями там +/-. Ну и если надо подчеркивание добавляю и прочие хотелки. И цвет также. На LCD пробовал, не сложно адаптируется.

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

Раз в разнообразии красота, тогда вариант - использование экранчика как единичного цифрового индикатора в многоместном. Так можно любого вида и вкуса цифры выводить :-)

b707
Offline
Зарегистрирован: 26.05.2017

я все еще не понимаю... вроде тема про шкалы была. Почему это вдруг съехало на обсуждение какой-то монстрозной безбуферной библиотеки на все случаи жизни?

Текущая чем не устраивает?

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

b707 пишет:

я все еще не понимаю... вроде тема про шкалы была. Почему это вдруг съехало на обсуждение какой-то монстрозной безбуферной библиотеки на все случаи жизни?

Текущая чем не устраивает?

Конечно шкалы и индикаторы. Просто изначально был концепт - один экран, одна шкала (теперь концепт можно расширить - много экранчиков, одна шкала). Понятно, что реальная поделка требует отражения многих величин, отсюда, как? на одну платку повесить много экранчиков. А дальше как сэкономить ресурсы, ну и приехали.

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

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

b707
Offline
Зарегистрирован: 26.05.2017

lilik пишет:

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

ну примитивы-то в библиотеку дописать можно и самому...

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

В виде функций смогу, в саму библиотеку - нет.

b707
Offline
Зарегистрирован: 26.05.2017

lilik пишет:

В виде функций смогу, в саму библиотеку - нет.


а в чем разница?

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

Содержимое функций вставлять в каждый скетч или файликом добавлять.

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

lilik пишет:

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

Какой промежуточный вариант между крайностями?

Если предположить, что первое утверждение верно (Картинка это множество хаотично расположенных  точек), то тем самым второе непременно становится ложным: координаты хаотично расположенных точек хранить не нужно, - они вычисляются датчиком случайных чисел.

Но я придерживаюсь обратного утверждения: картинка - это множество упорядоченно расположенных точек. Следовательно, можно проанализировать этот порядок и найти адекватный способ отображения картинки без буфера и без перебора по всем возможным вариантам.

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

Порядок надо как то описать, что бы отличить от хаоса (хаос - порядок который мы не можем описать :-), а потом найти соответствие описанию и байтам-столбцам экрана. Я без перебора не знаю как.

Сделал примитив первый.

///////////////////////// ЗВЕЗДА ////////////////////////////////
void primitiv_1(int x,int y,int r1,int r2,int n,float rotor) { //x,y координаты центра фигуры r1,r2 радиусы зубцов и впадин фигуры n число зубцов rotor угол поворота фигуры
 myOLED.clrScr(); // очищаем дисплей 
 for(float i=0+rotor;i<2*PI+rotor;i=i+2*PI/n){
  myOLED.drawLine(x+r1*cos(i) , y+r1*sin(i),x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n) ); 
  myOLED.drawLine(x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n),x+r1*cos(i+2*PI/n) , y+r1*sin(i+2*PI/n));
 }
 }
 /////////////////////////

весь скетч для 3 экранчиков

/////////////проверка одновременной работы 3 экранов на 3 разных индикаторах-шкалах
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
#define disp_1 12 // управляющие дисплееями выводы 
#define disp_2 11
#define disp_3 10

int t = 25; // пауза между считываниями потенциометра



void setup()
{
  ////// подключение всех дисплеев
  pinMode(disp_1, OUTPUT);
  digitalWrite(disp_1, HIGH);
  myOLED.begin();
  digitalWrite(disp_1, LOW);
  delay(50);
  //////
  pinMode(disp_2, OUTPUT);
  digitalWrite(disp_2, HIGH);
  myOLED.begin();
  digitalWrite(disp_2, LOW);
  delay(50);
  ////////
  pinMode(disp_3, OUTPUT);
  digitalWrite(disp_3, HIGH);
  myOLED.begin();
  digitalWrite(disp_3, LOW);
  delay(50);
  ////////

  myOLED.invert(0);//инверсия цвета
 

}

void loop()
{
   int p = map(analogRead(A0), 0, 1023, 0, 10); // считывание потенциометра и вычисление параметра
   
 // primitiv_1(63,32,20,30,9,PI/9); dis_1(); //обработка и обновление данных на 1 индикаторе
  primitiv_1(63,32,2*p,30,7,PI/9); dis_2(); //обработка и обновление данных на 2 индикаторе
  primitiv_1(63,32,10,30,5,PI/9*p); dis_3(); //обработка и обновление данных на 3 индикаторе
  delay(t);
}
////////////////////////////
////////////////////////////
///////////////////////////
void dis_1() { //функции обновления изображений на экранах
  digitalWrite(disp_1, HIGH); myOLED.update(); digitalWrite(disp_1, LOW);
}
void dis_2() {
  digitalWrite(disp_2, HIGH); myOLED.update(); digitalWrite(disp_2, LOW);
}
void dis_3() {
  digitalWrite(disp_3, HIGH); myOLED.update(); digitalWrite(disp_3, LOW);
}
/////////////////////////
/////////////////////////
///////////////////////// ЗВЕЗДА ////////////////////////////////
void primitiv_1(int x,int y,int r1,int r2,int n,float rotor) { //x,y координаты центра фигуры r1,r2 радиусы зубцов и впадин фигуры n число зубцов rotor угол поворота фигуры
 myOLED.clrScr(); // очищаем дисплей 
 for(float i=0+rotor;i<2*PI+rotor;i=i+2*PI/n){
  myOLED.drawLine(x+r1*cos(i) , y+r1*sin(i),x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n) ); 
  myOLED.drawLine(x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n),x+r1*cos(i+2*PI/n) , y+r1*sin(i+2*PI/n));
 }
 }
 /////////////////////////

6 аргументов позволяют анимировать разные вариации шкал-индикаторов (звёзды, шестерни, многоугольники, зрачок-радужка; приближение-удаление, трансформация, поворот-вращение, поступательное движение)

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

lilik пишет:

Не понял! Я чё не звезда Давида? Чем же Вы «пугать невежественных людей» будете?

Только когда будете делать, не забудьте, что звезда Давида должна уметь медленно гаснуть! Ибо сказано: «... стремительно  вывел  пальцем  на стене Соломонову звезду. Звезда вспыхнула и стала медленно  тускнеть,  как след пучка электронов на экране осциллографа. Я трижды плюнул через  левое плечо».

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

а чем звезда Магов не устроила?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

а чем звезда Магов не устроила?

Это Вы у Кристобаля Хозевича спросите.

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

ЕвгенийП пишет:

не забудьте, что звезда Давида должна уметь медленно гаснуть! 

Яркость и контрастность на этом экранчике практически не регулируются, хотя теоретически да. 

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

Радио - шкала. Взгрустнулось, придумал концепт сувенирной игрушки: вместо станций-городов станции-голоса родных и близких.

/////////////проверка одновременной работы 3 экранов на 3 разных индикаторах-шкалах
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
#define disp_1 12 // управляющие дисплееями выводы 
#define disp_2 11
#define disp_3 10

int t = 25; // пауза между считываниями потенциометра
extern uint8_t SmallFont[];


void setup()
{

  ////// подключение всех дисплеев
  pinMode(disp_1, OUTPUT);
  digitalWrite(disp_1, HIGH);
  myOLED.begin();
  digitalWrite(disp_1, LOW);
  delay(50);
  //////
  pinMode(disp_2, OUTPUT);
  digitalWrite(disp_2, HIGH);
  myOLED.begin();
  digitalWrite(disp_2, LOW);
  delay(50);
  ////////
  pinMode(disp_3, OUTPUT);
  digitalWrite(disp_3, HIGH);
  myOLED.begin();
  digitalWrite(disp_3, LOW);
  delay(50);
  ////////
  myOLED.setFont(SmallFont);
  myOLED.invert(0);//инверсия цвета


}

void loop()
{
  int p = map(analogRead(A0), 0, 1023, 0, 256); // считывание потенциометра и вычисление положения нити

  myOLED.clrScr(); // очищаем дисплей
  for (int i = 0; i < 128; i = i + 17) {
    myOLED.drawLine(i, 0, i, 15); // риски-метки шкалы
  }
  myOLED.print("A_city", 5, 25); myOLED.print("B_city", 35, 45); myOLED.print("C_city", 70, 25);// станции
  if (p < 128) {
    myOLED.drawLine(p, 0, p, 63);//указатель - нить
    myOLED.drawLine(p + 1, 0, p + 1, 63);
  }
  dis_3();
  myOLED.clrScr(); // очищаем дисплей
  for (int i = 0; i < 128; i = i + 17) {
    myOLED.drawLine(i, 0, i, 15); //риски-метки шкалы
  }
  myOLED.print("D_city", 5, 25); myOLED. print("E_city", 35, 45); myOLED.print("F_city", 70, 25); // станции

  if (p >= 128) {
    myOLED.drawLine(p - 128, 0, p - 128, 63);//указатель-нить
    myOLED.drawLine(p - 127, 0, p - 127, 63);
  }
  dis_2();
  delay(t);
}
////////////////////////////
////////////////////////////
///////////////////////////
void dis_1() { //функции обновления изображений на экранах
  digitalWrite(disp_1, HIGH); myOLED.update(); digitalWrite(disp_1, LOW);
}
void dis_2() {
  digitalWrite(disp_2, HIGH); myOLED.update(); digitalWrite(disp_2, LOW);
}
void dis_3() {
  digitalWrite(disp_3, HIGH); myOLED.update(); digitalWrite(disp_3, LOW);
}
/////////////////////////

 

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

Полностью "математическая шкала".

/////////////проверка одновременной работы 3 экранов на 3 разных индикаторах-шкалах
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
#define disp_1 12 // управляющие дисплееями выводы 
#define disp_2 11
#define disp_3 10

int t = 25; // пауза между считываниями потенциометра
extern uint8_t SmallFont[];
float a = 0.00; //

void setup()
{
  delay(50);
  ////// подключение всех дисплеев
  pinMode(disp_1, OUTPUT);
  digitalWrite(disp_1, HIGH);
  myOLED.begin();
  digitalWrite(disp_1, LOW);
  delay(50);
  //////
  pinMode(disp_2, OUTPUT);
  digitalWrite(disp_2, HIGH);
  myOLED.begin();
  digitalWrite(disp_2, LOW);
  delay(50);
  ////////
  pinMode(disp_3, OUTPUT);
  digitalWrite(disp_3, HIGH);
  myOLED.begin();
  digitalWrite(disp_3, LOW);
  delay(50);
  ////////
  myOLED.setFont(SmallFont);
  myOLED.invert(0);//инверсия цвета


}

void loop()
{
  a = 3 * PI / 16 + 3 * PI / 4 * (analogRead(A0)) / 1023; //угол поворота стрелки прибора в зависимости от полученных с потенциометра данных
  ////////////////////
  myOLED.clrScr(); // очищаем дисплей
  for (float i = 0; i < PI; i = i + PI / 16) {
    myOLED.drawLine(127 - 127 * cos(i), 127 - 127 * sin(i), 127 - 115 * cos(i), 127 - 115 * sin(i)  ); // риски-метки шкалы
  }
  myOLED.print("MIN", 0, 45);
  if (a < PI / 2) {
    myOLED.drawLine(135, 127, 127 - 140 * cos(a), 127 - 140 * sin(a)  ); // стрелка
  }
  dis_3();
  ///////////////////
  myOLED.clrScr(); // очищаем дисплей

  for (float i = 0; i < PI; i = i + PI / 16) {
    myOLED.drawLine(0 - 127 * cos(i), 127 - 127 * sin(i), 0 - 115 * cos(i), 127 - 115 * sin(i)  ); // риски-метки шкалы
  }
  myOLED.print("MAX", 107, 45);
  if (a > PI / 2) {
    myOLED.drawLine(-8, 127, 0 - 140 * cos(a), 127 - 140 * sin(a)  ); //стрелка
  }
  dis_2();

  delay(t);
}
////////////////////////////
////////////////////////////
///////////////////////////
void dis_1() { //функции обновления изображений на экранах
  digitalWrite(disp_1, HIGH); myOLED.update(); digitalWrite(disp_1, LOW);
}
void dis_2() {
  digitalWrite(disp_2, HIGH); myOLED.update(); digitalWrite(disp_2, LOW);
}
void dis_3() {
  digitalWrite(disp_3, HIGH); myOLED.update(); digitalWrite(disp_3, LOW);
}
/////////////////////////

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

Ещё концепт, который не буду макетировать.

b707
Offline
Зарегистрирован: 26.05.2017

Шкала из сообщения #12, битмап из сообщения 25

Выведено на 4 RGB матрицы 64х32, общий размер как у ТС - 128х64. Контроллер - STM32F103

фото долго корежил, чтоб не так жгло глаза :) - вживую смотрится посимпотичнее

Размер табло 50х25 см

b707
Offline
Зарегистрирован: 26.05.2017

b707
Offline
Зарегистрирован: 26.05.2017

хотел еще вот этот зеленым нарисовать, но кода к нему не нашел. lilik, выложите, если не трудно.

Остальные на большом экране, имхо, смотрется не будут

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

Здорово смотрится!

///////////// индикатор по мотивам "зёлёного глаза на 6Е5С"
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
extern const unsigned char schkala_A[];

int t=30;// пауза между считываниями потенциометра
float a=0.00;//
int dlina=33;
void setup()
{
 myOLED.begin();
 myOLED.invert(0);//инверсия цвета
}

void loop()
{
myOLED.drawBitmap(0, 0,schkala_A, 128, 64);// рисование  контура глаза
 a=-PI*analogRead(A0)/2048+PI/2;//угол конуса расхождения лучей
for( float i=a;i>=0;i=i-0.12){
myOLED.drawLine(63, 27, 63+cos(i)*dlina, 27+sin(i)*dlina);//
myOLED.drawLine(63, 27, 63+cos(PI-i)*dlina, 27+sin(PI-i)*dlina);//  
 }
 myOLED.update(); delay(t); 
}
#include <avr/pgmspace.h>



const unsigned char schkala_A[]PROGMEM = {
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X80,0X80,0XC0,0XC0,0XC0,
0XC0,0XC0,0XE0,0XE0,0XE0,0XE0,0XE0,0XE0,0XE0,0XF0,0XF0,0XF0,0XF0,0XF0,0XF0,0XF0,
0XF0,0XF0,0XF0,0XF0,0XF0,0XF0,0XF0,0XE0,0XE0,0XE0,0XE0,0XE0,0XE0,0XE0,0XC0,0XC0,
0XC0,0XC0,0X80,0X80,0X80,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X80,0XC0,0XC0,0XE0,0XE0,0XF0,
0XF0,0XF8,0XF8,0XFC,0XFC,0X7E,0X3E,0X3F,0X3F,0X1F,0X1F,0X1F,0X0F,0X0F,0X0F,0X07,
0X07,0X07,0X07,0X03,0X03,0X03,0X03,0X03,0X03,0X01,0X01,0X01,0X01,0X01,0X01,0X01,
0X01,0X01,0X01,0X01,0X01,0X01,0X01,0X01,0X03,0X03,0X03,0X03,0X03,0X03,0X07,0X07,
0X07,0X0F,0X0F,0X0F,0X1F,0X1F,0X1F,0X3F,0X3E,0X3E,0X7E,0XFC,0XFC,0XF8,0XF8,0XF0,
0XF0,0XE0,0XE0,0XC0,0XC0,0X80,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0XC0,0XC0,
0XE0,0XF0,0XF0,0XF8,0XFC,0X7C,0X7E,0X3F,0X1F,0X1F,0X0F,0X0F,0X1F,0XFF,0XFF,0XFF,
0XFF,0X7F,0X0F,0X03,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X80,0XE0,0XF0,0XF8,0XFC,0XFC,0XFE,0XFE,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFE,0XFE,0XFC,0XFC,0XF8,0XF0,0XE0,0X80,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0X1F,0XFF,0XFF,
0XFF,0XFF,0XFF,0X0F,0X07,0X07,0X0F,0X1F,0X1F,0X3E,0X7C,0XFC,0XF8,0XF0,0XF0,0XE0,
0XC0,0XC0,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X80,0XC0,0XE0,0XF0,0XF8,0XFC,0XFC,0XFE,0X3F,0X1F,0X0F,0X0F,
0X07,0X03,0X01,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,
0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,
0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X03,0X07,
0X0F,0X1F,0X3F,0X3F,0XFE,0XFE,0XFC,0XF8,0XF0,0XE0,0XC0,0X80,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X03,0X07,0X0F,0X1F,0X1F,0X3F,0X7F,0XFF,0XFF,0XFF,0XFE,0XFC,0XFC,
0XF8,0XF0,0XE0,0XC0,0XC0,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0X3F,0XFF,0XFF,
0XFF,0XF0,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X03,0X0F,0X1F,0X3F,0X7F,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X7F,0X7F,0X3F,0X1F,0X0F,0X03,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0XF0,0XFF,
0XFF,0XFF,0X3F,0X07,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0XC0,0XC0,0XE0,0XF0,0XF8,
0XFC,0XFC,0XFE,0XFF,0XFF,0XFF,0X7F,0X3F,0X1F,0X0F,0X0F,0X07,0X03,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X03,0X03,0X07,0X0F,
0X1F,0X1F,0X3F,0X7F,0X7F,0XFF,0XFF,0XFE,0XFE,0XFC,0XFC,0XF8,0XF0,0XF0,0XE1,0XE7,
0XCF,0XFF,0XFF,0XFE,0XF8,0XF0,0XC0,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X01,0X01,0X01,
0X01,0X01,0X01,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0XE0,0XF0,0XF8,0XFE,0XFF,0XFF,0XCF,
0XE7,0XE1,0XF0,0XF0,0XF8,0XFC,0XFC,0XFE,0XFE,0XFF,0XFF,0X7F,0X7F,0X3F,0X1F,0X1F,
0X0F,0X07,0X03,0X03,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X01,0X03,0X03,0X07,0X07,0X0F,0X0F,0X1F,0X1F,
0X3F,0X3F,0X7F,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFC,0XF8,0XF8,0XF0,0XF0,0XE0,
0XC0,0XC0,0XC0,0X80,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X80,0XC0,0XC0,0XE0,
0XE0,0XF0,0XF0,0XF8,0XFC,0XFC,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0X7F,0X7F,0X3F,0X3F,
0X1F,0X1F,0X0F,0X0F,0X07,0X07,0X03,0X03,0X01,0X01,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X01,0X01,0X03,0X03,0X03,0X07,0X07,0X07,0X07,
0X0F,0X0F,0X0F,0X0F,0X0F,0X1F,0X1F,0X1F,0X1F,0X1E,0X1E,0X1E,0X1E,0X1E,0X3E,0X3E,
0X3E,0X3E,0X1E,0X1E,0X1E,0X1E,0X1E,0X1F,0X1F,0X1F,0X1F,0X0F,0X0F,0X0F,0X0F,0X0F,
0X07,0X07,0X07,0X07,0X03,0X03,0X03,0X01,0X01,0X01,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00
};

 

b707
Offline
Зарегистрирован: 26.05.2017

как-то так...

 

в общем, на маленьком экранчике с маленькими пикселями все прикольнее...

На матрице реально только термометр симпотно вышел, жена даже сказала - хочу такой в корридоре повесить :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А зачем тебе внутрисемейное Око Саурона?  :)))

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

А зачем тебе внутрисемейное Око Саурона?  :)))

как-то так :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

b707 пишет:

На матрице реально только термометр симпотно вышел, жена даже сказала - хочу такой в корридоре повесить :)

Тут от дистанции восприятие сильно зависит... и от формы пикселя.

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

DetSimen пишет:

Я попробую зрачок (а мож и весь глаз) "чисто математически нарисовать" :-) 

sadman41
Offline
Зарегистрирован: 19.10.2016

Я тут давеча смотрел про хоббитов этих... В кино показано, что зрачок ока Саурона есть фигура этого самого Саурона и вокруг него пламень адский беснуется. Т.е. это не аморфная фигура, а вполне себе оформленная.

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

Ну, да. Только так можно на цветной матрице пробовать :-)

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

Думал это самая странная шкала, ан нет.

/////////////проверка одновременной работы 3 экранов на 3 разных индикаторах-шкалах
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
#define disp_1 12 // управляющие дисплееями выводы 
#define disp_2 11
#define disp_3 10

int t = 25; // пауза между считываниями потенциометра
extern uint8_t SmallFont[];
float a = 0.00; //

void setup()
{
  delay(50);
  ////// подключение всех дисплеев
  pinMode(disp_1, OUTPUT);
  digitalWrite(disp_1, HIGH);
  myOLED.begin();
  digitalWrite(disp_1, LOW);
  delay(50);
  //////
  pinMode(disp_2, OUTPUT);
  digitalWrite(disp_2, HIGH);
  myOLED.begin();
  digitalWrite(disp_2, LOW);
  delay(50);
  ////////
  pinMode(disp_3, OUTPUT);
  digitalWrite(disp_3, HIGH);
  myOLED.begin();
  digitalWrite(disp_3, LOW);
  delay(50);
  ////////
  myOLED.setFont(SmallFont);
  myOLED.invert(0);//инверсия цвета


}

void loop()
{
  a = 2.6 * PI / 16 + 3 * PI / 4 * (analogRead(A0)) / 1023; //угол поворота стрелки прибора в зависимости от полученных с потенциометра данных
  ////////////////////
  myOLED.clrScr(); // очищаем дисплей
  for (float i = 0; i < PI; i = i + PI / 15) {
    myOLED.drawLine(135 - 127 * cos(i), 127 - 127 * sin(PI / 3), 135 - 105 * cos(i), 127 - 105 * sin(PI / 3)  ); // риски-метки шкалы
  }
  myOLED.printNumI(analogRead(A0) / 10, 127 - 140 * cos(a) , 0); //бегущее числовое значение величины
  if (a < PI / 2) {
    myOLED.drawLine(135, 127, 127 - 140 * cos(a), 127 - 140 * sin(1.2 * PI / 4)  ); // стрелка
  }
  dis_3();
  ///////////////////
  myOLED.clrScr(); // очищаем дисплей

  for (float i = 0; i < PI; i = i + PI / 15) {
    myOLED.drawLine(-8 - 127 * cos(i), 127 - 127 * sin(PI / 3), -8 - 105 * cos(i), 127 - 105 * sin(PI / 3)  ); // риски-метки шкалы
  }
  myOLED.printNumI(analogRead(A0) / 10, 0 - 140 * cos(a) , 0); //бегущее числовое значение величины
  if (a > PI / 2) {
    myOLED.drawLine(-8, 127, 0 - 140 * cos(a), 127 - 140 * sin(1.2 * PI / 4)  ); //стрелка
  }
  dis_2();

  delay(t);
}
////////////////////////////
////////////////////////////
///////////////////////////
void dis_1() { //функции обновления изображений на экранах
  digitalWrite(disp_1, HIGH); myOLED.update(); digitalWrite(disp_1, LOW);
}
void dis_2() {
  digitalWrite(disp_2, HIGH); myOLED.update(); digitalWrite(disp_2, LOW);
}
void dis_3() {
  digitalWrite(disp_3, HIGH); myOLED.update(); digitalWrite(disp_3, LOW);
}
/////////////////////////

 

lilik
Offline
Зарегистрирован: 19.10.2017
/////////////проверка одновременной работы 3 экранов на 3 разных индикаторах-шкалах
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
#define disp_1 12 // управляющие дисплееями выводы 
#define disp_2 11
#define disp_3 10

extern uint8_t SmallFont[];
int t = 25; // пауза между считываниями потенциометра
int p=0;//


void setup()
{
  ////// подключение всех дисплеев
  pinMode(disp_1, OUTPUT);
  digitalWrite(disp_1, HIGH);
  myOLED.begin();
  digitalWrite(disp_1, LOW);
  delay(50);
  //////
  pinMode(disp_2, OUTPUT);
  digitalWrite(disp_2, HIGH);
  myOLED.begin();
  digitalWrite(disp_2, LOW);
  delay(50);
  ////////
  pinMode(disp_3, OUTPUT);
  digitalWrite(disp_3, HIGH);
  myOLED.begin();
  digitalWrite(disp_3, LOW);
  delay(50);
  ////////
  myOLED.setFont(SmallFont);
  myOLED.invert(0);//инверсия цвета
 

}

void loop()
{
  
   p = map(analogRead(A0), 0, 1023, 0, 100); // считывание потенциометра и вычисление параметра
  

myOLED.clrScr(); // очищаем дисплей   
pribor_A("A",30,32,8,PI/2);//прибор А
pribor_A("B",98,32,12,0);// прибор В
dis_3(); //обработка и обновление данных на 3 индикаторе
myOLED.clrScr(); // очищаем дисплей  
pribor_A("C",30,32,24,PI/6);// прибор С
pribor_A("E",98,32,4,PI);// прибор Е
dis_2(); //обработка и обновление данных на 2 индикаторе

  delay(t);
}
////////////////////////////
////////////////////////////
///////////////////////////
void dis_1() { //функции обновления изображений на экранах
  digitalWrite(disp_1, HIGH); myOLED.update(); digitalWrite(disp_1, LOW);
}
void dis_2() {
  digitalWrite(disp_2, HIGH); myOLED.update(); digitalWrite(disp_2, LOW);
}
void dis_3() {
  digitalWrite(disp_3, HIGH); myOLED.update(); digitalWrite(disp_3, LOW);
}
/////////////////////////
/////////////////////////
///////////////////////// функция рисования стрелки ////////////////////////////////
void primitiv_1(int x,int y,int r1,int r2,int n,float rotor) { //x,y координаты центра фигуры r1,r2 радиусы зубцов и впадин фигуры n число зубцов rotor угол поворота фигуры
  for(float i=0+rotor;i<1*PI+rotor;i=i+2*PI/n){
  myOLED.drawLine(x+r1*cos(i) , y+r1*sin(i),x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n) ); 
  myOLED.drawLine(x+r2*cos(i+PI/n) , y+r2*sin(i+PI/n),x+r1*cos(i+2*PI/n) , y+r1*sin(i+2*PI/n));
 }
 }
 ///////////////////////// функция рисования прибора-шкалы //////////////////////////
void pribor_A (String str, int x1,int y1,int n1,float rotor1){//str название шкалы x1,y1 координаты положения центра n1 число делений rotor1 начальный угол положения стрелки
for(int i=22;i<29;i++){primitiv_1(x1,y1,7,i,2,(PI/50)*p+rotor1);}//стрелка
for(int i=6;i<9;i++){myOLED.drawCircle(x1,y1,i);}

myOLED.drawCircle(x1,y1,31);//шкала
for(float i=0;i<2*PI;i=i+2*PI/n1){myOLED.drawLine(x1-25*cos(i),y1-25*sin(i),x1-31*cos(i),y1-31*sin(i));}
myOLED.print(str,x1-20,y1-5);// название шкалы
  }

sadman41
Offline
Зарегистрирован: 19.10.2016

Во как в накрыло человека индикатором. Яркий пример того, что ардуина - хобби.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

lilik пишет:

Думал это самая странная шкала, ан нет.

Самая странная на приборке BMW актуального поколения. 

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

sadman41 пишет:
Во как в накрыло человека индикатором. Яркий пример того, что ардуина - хобби.

Это правда, понимаю что "дедство", но рисовалки затягивают.

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

Ну почему жеж )))

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

Ну это совсем хитрые, особенно "красные стебельки" :-) Это для фиксации точек пересечения стрелок?

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

lilik пишет:

Ну это совсем хитрые, особенно "красные стебельки" :-) Это для фиксации точек пересечения стрелок?

По пересечению двух стрелок определяем SWR (Коэффициент стоячей волны)

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

Такую проще имитировать по картинке, чем "рисовать математикой".

man_200
Offline
Зарегистрирован: 29.04.2016

Как вариант - со стрелкой, но по середине еще и цифровая шкала на 3-4 цифры

По типу аналогово-цифровых приборов.

Либо как у тестеров - цифровая шкала, а внизу аналоговая линейка

Ну и напоследок натюрморт - шкала со стрелкой, по середине цифровая, а внизу еще и линейка

Причем все шкалы схемно можно было бы разъединить и использовать на отображение отдельных датчиков или с вариациями:

две от одного датчика, третья от отдельного.

Т.е. создай универсальную базу, а что измерять и чем управлять - ребята придумают

Так думаю

P.S. стоит подумать о применении других дисплеев, в том числе и TFT под разный размер

Радиолюбители благодарны будут

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

man_200 пишет:

Как вариант - со стрелкой, но по середине еще и цифровая шкала на 3-4 цифры

По типу аналогово-цифровых приборов.

Либо как у тестеров - цифровая шкала, а внизу аналоговая линейка

Ну и напоследок натюрморт - шкала со стрелкой, по середине цифровая, а внизу еще и линейка

Причем все шкалы схемно можно было бы разъединить и использовать на отображение отдельных датчиков или с вариациями:

две от одного датчика, третья от отдельного.

Т.е. создай универсальную базу, а что измерять - ребята придумают

Так думаю

Это явно нерациональный подход к проектированию.

Рациональный может быть реализован одним из двух вариантов:

1. Единственный прибор, имеющий несколько режимов работы, между которыми можно выбирать - либо однократно в процессе создания, либо многократно переключать в процессе работы.

2. Набор разных приборов, имеющих одинаковый программный интерфейс. В случае ООП - наследников одного базового класса, различающихся только способом отображения.

man_200
Offline
Зарегистрирован: 29.04.2016

В случае использования платформы STM32, с его двумя портами АЦП, высокой тактовой частотой и другими плюшками, программно можно будет все это сотворить (Радиокот.ру осциллографы, измеритель RLC и т.п. одновременно измеряется куча параметров). 

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

А изначально идея с такими разными шкалами и понятными инсталяциями очень хороша. Спасибо разработчику!

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

man_200 пишет:

Как вариант - со стрелкой, но по середине еще и цифровая шкала на 3-4 цифры

P.S. стоит подумать о применении других дисплеев, в том числе и TFT под разный размер

Радиолюбители благодарны будут

Да, только цифровая не дублирует, а уточняет показания стрелочной, по аналогии с нониусом. 

Про другие экранчики не думал, изначально хотелось визуализацию посмотреть на маленьком по формуле - один экран, один прибор ( как теперь выяснилось шкал может быть две :-)

 

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

andriano пишет:

1. Единственный прибор, имеющий несколько режимов работы, между которыми можно выбирать - либо однократно в процессе создания, либо многократно переключать в процессе работы.

2. Набор разных приборов, имеющих одинаковый программный интерфейс. В случае ООП - наследников одного базового класса, различающихся только способом отображения.

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

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

#include <Wire.h>//Подключаю библиотеку протокола I2C.

int K = 0; // переменная хранения числа-столбца 8 пикселей


//////////////////////////////////////////////////////////////////////
//Предварительно создам функции ввода команд и данных в дисплей.
void oledCommand(int comm) {
  Wire.beginTransmission(0x3C);//Начинаем передачу команд устройству с адресом 0x3C.
  Wire.write(0x00);//Сообщаем дисплею, что следующее передаваемое значение - команда.
  Wire.write(comm);//Передаем команду.
  Wire.endTransmission();//Завершаем передачу данных.
}
///////////////////////////////////////////////////////////////////////
void oledData(int data) {
  Wire.beginTransmission(0x3C);//Начинаем передачу данных устройству с адресом 0x3C.
  Wire.write(0x40);//Сообщаем дисплею, что следующее передаваемое значение - данные, которые необходимо вывести на дисплей.
  Wire.write(data);//Передаем данные.
  Wire.endTransmission();//Завершаем передачу данных.
}

/////////////////////////////////////////////////////////////////////
void setup() {
  ///////////////////
  pinMode(11, OUTPUT);
  digitalWrite(11, HIGH);
  delay(100);
  ///////////////////
  Wire.begin();

  //процесс инициализации частично команды необязательны, т.к. имеют выбранное значение после RESET
  oledCommand(0xAE);//выключение дисплея
  oledCommand(0xD5);// Частота обновления экрана
  oledCommand(0x80);
  oledCommand(0xD3);// Смещение изображения на дисплее (Offset)
  oledCommand(0x0);
  oledCommand(0x40);
  oledCommand(0x8D);//включение емкостного умножителя
  oledCommand(0x14);
  oledCommand(0x20);//настройка адресации
  oledCommand(0x00);// 0х00 для горизонтальной, 0х01 для вертикальной, 0х02 для постраничной адресации
  oledCommand(0xA1);//отражение по горизонтали, для отображения справа налево необходимо использовать команду 0xA0
  oledCommand(0xC8);//отражение по вертикали, 0xC0 для переворота изображения по вертикали.
  //Одновременное использование команд 0xC8 и 0xA1 или 0xA0 и 0xC0 позволяет повернуть изображение на 180 градусов.
  oledCommand(0xDA);
  oledCommand(0x12);
  oledCommand(0x81);//установка контрастности дисплея
  oledCommand(0xCF);
  oledCommand(0xD9);
  oledCommand(0xF1);
  oledCommand(0xDB); // установка Vcomh(влияет на яркость)
  // oledCommand (0x30); // 0x00 - 0,65Vcc; 0x20 - 0,77Vcc; 0x30 - 0,83Vcc
  oledCommand(0x40);
  oledCommand(0xA4);
  oledCommand(0xA6);//инверсия дисплея, 0xA6 для отключения инверсии, 0xA7 для включения инверсии цвета.
  oledCommand(0xAF);//включение дисплея

  Wire.setClock( 400000L );

}

void loop() {

  int R = map(analogRead(A0), 0, 1020, 0, 63);// выставляем потенциометром координаты центра фигуры - двигаем её по экрану
  krug_(63, 32, R); //круг в центре экрана переменного радиуса

  delay(25);
}
///////////////////////////////////////////////////////
void krug_(int X, int Y, int R) {
  /////////////////////
  oledCommand(0x21);//установка столбца
  oledCommand(0);//Начальный столбец.
  oledCommand(127);//Конечный столбец.
  oledCommand(0x22);//установка страницы
  oledCommand(0);//Начальная страница.
  oledCommand(7);//Конечная страница.
  //////////////////////
  for ( int i = 0; i < 1024; i++) { //перебираем все столбики экрана
    int N = i / 128; // определяем номер страницы экраны по значению счётчика столбиков
    int x = i - 128 * N; // определяем координату всех пикселей в столбике текущем
    for (int y = 8 * N; y < 8 * N + 8; y++) { // перебираем координаты всех пикселей столбика
      if (((x - X) * (x - X)) + ((y - Y) * (y - Y)) <= R * R/*&&((x - X) * (x - X)) + ((y - Y) * (y - Y)) >=( R-1)*(R-1)*/  ) { // проверяем принадлежит ли пиксель данной фигуре (круг или //окружность)
        int bi = y % 8;
        K = K | (1 << bi); // или bitSet(K, bi);- вносим бит 1 в число-столбик если принадлежит пиксель фигуре
      }
    }
    oledData(K); K = 0; // отправляем "число-столбик в экран"
  }
}

Всё таки не удержался и решил проверить графику на экране без использования буфера. В общем случае можно рисовать разные примитивы с заметной глазу отрисовкой экрана. Выше пример для круга и окружности - с 3 аргументами функция. Вся суть концепции в 83 строке. Для нескольких фигур в одновременной отрисовке надо писать через "или" множество уравнений-условий в круглых скобках. В связи с этим пока архитектура многофигурного скетча не ясна.

 А так путь к безбуферной графической библиотеке для "головастиков" (это любя,.. тех у кого светлая голова :-) открыт. Правда уравнения фигур придётся адаптировать под вычислялки Ардуино (окружность одолел сходу, а вот отрезок нет). 

man_200
Offline
Зарегистрирован: 29.04.2016

Как правило пределы шкал стандартны: 0-0,1; 0-0,3; 0-0,5; 0-1,0, а далее увеличивающиеся на порядок: 0-1; 0-3;...... 0-10, и т.д. (бывают 0-2.0). И шаг соответственно: 1/10 (1/5, как в первом посту, редко 1/2), как правило - это стандарт. А переключение между шкалами по кругу - отдельной кнопкой или кнопкой энкодера (для управления параметрами внешних устройств).

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

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

lilik пишет:

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

Вот как раз так - не надо.

Ардуина хороша тем, что в ней используется Си++, а Си++ хорош тем, что в нем есть такое понятие как класс. Вот с классом и надо работать. Минимум - два метода: в одном настройка внешнего вида (может быть несколько параметров), в другом - единственный параметр - текущие показания.

Не следует перегружать функцию, в которую передаются показания, еще и какими-то дополнительными параметрами.

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

lilik пишет:

 

 

Всё таки не удержался и решил проверить графику на экране без использования буфера. В общем случае можно рисовать разные примитивы с заметной глазу отрисовкой экрана. Выше пример для круга и окружности - с 3 аргументами функция. Вся суть концепции в 83 строке. Для нескольких фигур в одновременной отрисовке надо писать через "или" множество уравнений-условий в круглых скобках. В связи с этим пока архитектура многофигурного скетча не ясна.

 А так путь к безбуферной графической библиотеке для "головастиков" (это любя,.. тех у кого светлая голова :-) открыт. Правда уравнения фигур придётся адаптировать под вычислялки Ардуино (окружность одолел сходу, а вот отрезок нет). 

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

1. Перебирать точку за точкой и для каждой проверять условие - это издевательство над контроллером. Правильно - рисовать по строкам. Или, в случае данного конкретного дисплея, - по столбцам. Для каждого столбца вычисляем начальную и конечную точку отрезка, который нужно закрасить. Собственно, достаточно вычислить одну точку, а вторая будет расположена симметрично. И закрашивать уже целиком вертикальный столбец.

2. Собственно, все построение разбивается на закраску не зависящих друг от друга столбцов. Следовательно, экранный буфер для всего изображения - не нужен. А если пойти чуть дальше - то не нужен и буфер даже для одного столбца, т.к. все изображение состоит из примитивов трех типов: закрашенный 8-пиксельный фрагмент, не закрашенный фрагмент и частично закрашенный фрагмерт. При этом частичная закраска не может быть с промежутками, т.е. одна сторона фрагмента всегда закрашена, а противоположная - всегда нет. При этом таких частично закрашенных фрагментов может быть два вида: закрашенный сверху и закрашенный снизу. Для каждого из видов существует по 7 вариантов. Т.е. всего 16 примитивов, которыми можно рисовать без использования буфера.