Преодоление проблем с экраном 0.96 128X64 OLED LCD I2C SSD1306

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

Преодоление проблем с экраном 0.96 128X64 OLED LCD I2C SSD1306

Думал, в каком разделе поместиь эту тему: в аппаратном или программном. Т.к. сложившаяся практика требует решения аппаратных проблем программным путем, посчитал, что этот вопрос скорее аппаратный. Да и посвящен он одному конкретному изделию, а не общим принципам программирования. Поэтому - здесь.
На данном форуме уже поднимался вопрос насчет данного изделия: http://arduino.ru/forum/programmirovanie/pomogite-razobratsya-s-displeem-oled-lcd-display-i2c-096-iic-serial-128x64

Купил вот такой прибор: http://iarduino.ru/shop/Displei/ekran-128x64-oled-lcd-led-dlya-arduino.html
Собственно, именно здесь и покупал, поэтому, если кто брал здесь же, то настоящая заметка может оказаться полезной.

Пытался запустить его со следующими библиотеками:

1. http://arduino-project.net/russkie-ukrainskie-shrifty-oled-i2c/

2. http://blog.oscarliang.net/arduino-oled-display-library/

3. http://www.adafruit.com/category/63_98

Вариант 3 не компилируется последней версией компилятора. После пропихивания (т.е. изменений таких, чтобы компилятор не ругался) программа так и не заработала, ну да ладно, в коде обнаружил экранный буфер, поэтому интерес к нему пропал.

Вариант 2 также не работал пока... не запустил вариант 1. После этого вариант 2 заработал. Если выключить питание, а затем включить (отключить и включить USB кабель), ситуация повторяется, т.е. не работет до первого запуска примеров из варианта 1.
Другими словами, в варианте 2 где-то что-то недоинициализируется, что, возможно, работает на оригинальном дисплее, но не работает на его китайской копии.

Вариант 1. В принципе, все работает, но есть два недостатка:
- Автор явно указывает, что библиотека несовместима с Wire, а для подключения других устройств по I2C рекомендует использовать другую пару контактов.
- Библиотека использует экранный буфер.

Собственно, дисплей приобретался для робота, а потому категорически не устраивают оба недостатка.
К I2C планировалось подключать кучу периферии вследствии того, что наблюдается острый дефицит ног контроллера, и выделить еще пару не представляется возможным. Равно как и обходиться без других I2C приборов.
Экранный буфер категорически не устраивает потому, что ТОЛЬКО этот буфер отъедает 2/3 всей доступной памяти. С этим можно мириться, если дисплей - центральный прибор в системе, построенной на Arduino (например, часы), но категоричекски неприемлемо, если ему отводится лишь роль вспомогательного средства индикации.
Подсчет простой:
- в Arduino Uno имеется 2 килобайта оперативной памяти (переходить на Мегу из-за одного только дисплея не хочу),
- среда разработки настойчиво предлагает оставлять для стека не менее 0.5 килобайта памяти, да и с использованием сторонних библиотек с такой оценкой трудно не согласиться,
- примерно 0.2-0.3 килобайт занимает каждая из подключаемых библиотек,
- экранный буфер требует 1 килобайт.
Итого: если использовать экранный буфер, то: экранный буфер + стек + библиотека управления дисплеем займет 1.7К из 2.0К, а на все остальное останется только 0.3К. Очевидно, что если требует подключать еще электромоторы, сервопривод, многочисленные датчики, да еще и писать логику управления роботом, памяти не хватит.

Единственная библиотека, способная обходиться без экранного буфера - вариант 2. Поэтому на нем и решил остановиться.
Путем сравнения с вариантом 1 выделил фрагмент, которого не хватало варианту 2 для полноценной инициализации дисплея.
В конец процедуры OzOLED::init() в файле OzOLED.cpp необходимо внести следующий код:
 

// Additional command
    OzOled.setPowerOff();
    OzOled.sendCommand(ASA_SET_DISPLAY_CLOCK_DIV_RATIO);
    OzOled.sendCommand(0x80);
    OzOled.sendCommand(ASA_SET_MULTIPLEX_RATIO);
    OzOled.sendCommand(0x3F);
    OzOled.sendCommand(ASA_SET_DISPLAY_OFFSET);
    OzOled.sendCommand(0x0);
    OzOled.sendCommand(ASA_SET_START_LINE | 0x0);
    OzOled.sendCommand(ASA_CHARGE_PUMP);
        OzOled.sendCommand(0x14);
    OzOled.sendCommand(ASA_MEMORY_ADDR_MODE);
    OzOled.sendCommand(0x00);
    OzOled.sendCommand(ASA_SET_SEGMENT_REMAP | 0x1);
    OzOled.sendCommand(ASA_COM_SCAN_DIR_DEC);
    OzOled.sendCommand(ASA_SET_COM_PINS);
    OzOled.sendCommand(0x12);
    OzOled.setBrightness(0xCF);
    OzOled.sendCommand(ASA_SET_PRECHARGE_PERIOD);
        OzOled.sendCommand(0xF1);
    OzOled.sendCommand(ASA_SET_VCOM_DESELECT);
    OzOled.sendCommand(0x40);
    OzOled.sendCommand(ASA_DISPLAY_ALL_ON_RESUME);
    OzOled.setNormalDisplay();
    OzOled.setPowerOn();

а перед ним разместить определение команд, которые не описаны в OzOLED.h (лучше помещать их в OzOLED.cpp, т.к. снаружи они не нужны):
 

// SSD1306 Commandset
// ------------------
// Fundamental Commands
#define ASA_DISPLAY_ALL_ON_RESUME            0xA4
// Addressing Setting Commands
#define ASA_MEMORY_ADDR_MODE                0x20
// Hardware Configuration Commands
#define ASA_SET_START_LINE                0x40
#define ASA_SET_SEGMENT_REMAP                0xA0
#define ASA_SET_MULTIPLEX_RATIO                0xA8
#define ASA_COM_SCAN_DIR_DEC            0xC8
#define ASA_SET_DISPLAY_OFFSET            0xD3
#define ASA_SET_COM_PINS                0xDA
#define ASA_CHARGE_PUMP               0x8D
// Timing & Driving Scheme Setting Commands
#define ASA_SET_DISPLAY_CLOCK_DIV_RATIO        0xD5
#define ASA_SET_PRECHARGE_PERIOD        0xD9
#define ASA_SET_VCOM_DESELECT                0xDB

После этого библиотека должна заработать даже на китайских дисплеях.

Но это еще не все.

Я, как крыловскавя мартышка, не вижу мелкие буковки шрифта 8х8 пикселей на дисплее резмером меньше дюйма. Даже в очках. Поэтому возникла потребность в более крупном шрифте, да вот беда, крупные шрифты занимают довольно много места, на этот раз во флеш-памяти, а ее тоже не слишком много - всего 32К. Дабы оставить себе свободу в программировании алгоритмов поведения робота, решил обойтись имеющимся фонтом 8х8, растянув его до 12х16 и 16х16. Получилось немного угловато, зато экономно по памяти. Шрифт 16х16, очевидно, рисуется квадратиками 2х2 пискеля, а с шрифтом 12х16 - хитрее: удваивается не каждый, а только каждый второй столбец пикселей. В результате есть два варианта: в одном удваиваются только четные столбцы, а в другом - нечетные. Решил реализовать оба варианта, а потом постепенно решить, который из них лучше смотрится.
Мудрить не стал, как и в исходном коде, для вывода разными фрифтами используются разные функции (описание в файле OzOLED.h):
 

// исходные функции - фонт 8х8
    void printChar(char c, byte X=255, byte Y=255);
    void printString(const char *String, byte X=255, byte Y=255, byte numChar=255);
// новые функции - фонт 16х16
    void printChar16(char c, byte X=255, byte Y=255);    // font 16x16
    void printString16(const char *String, byte X, byte Y, byte numChar=255);    // font 16x16
// новые функции - фонт 12х16, вариант a
    void printChar12a(char c, byte X=255, byte Y=255);    // font 12x16
    void printString12a(const char *String, byte X, byte Y, byte numChar=255);    // font 12x16
// новые функции - фонт 12х16, вариант b
    void printChar12b(char c, byte X=255, byte Y=255);    // font 12x16
    void printString12b(const char *String, byte X, byte Y, byte numChar=255);    // font 12x16
// далее - старые функции - их аналогов делать не стал, если кому понадобятся, можно сделать по образу и подобию имеющихся
    byte printNumber(long n, byte X=255, byte Y=255);
    byte printNumber(float float_num, byte prec=6, byte Y=255, byte numChar=255);
    void printBigNumber(const char *number, byte column=0, byte page=0, byte numChar=255);
    void drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height);
// новыя функция, позиционирующая по X с шагом 4 пикселя - нужна для шрифта 12х16 (исходная setCursorXY позиционирует с шагом 8 - целый символ 8х8)
    void setCursorX2Y(byte Column, byte Row); // X * 4 pixels, Y * 8 pixels

И их реализация в OzOLED.cpp:
 

unsigned int EnlardeByte2Word(char b)
{
    unsigned int d = 0;
    for (byte i = 0; i < 8; i++)
    {
        unsigned int e = (((unsigned int)b) & (1 << i)) << i;
        d = d | e | (e << 1);
    }
    return d;
}

void OzOLED::printChar16(char C, byte X, byte Y){
    setCursorXY(X, Y);
    if(C < 32 || C > 127)        //Ignore unused ASCII characters.
        C='*';        //star - indicate characters that can't be displayed
    unsigned int m = 0;
    unsigned char n[8];

    for ( byte i=0; i<8; i++) {
        m = EnlardeByte2Word(pgm_read_byte(&BasicFont[C-32][i]));
        sendData(lowByte(m));
        sendData(lowByte(m));
        n[i] = highByte(m);
    }
    setCursorXY(X, Y+1);

    for(byte i=0; i<8; i++) {
        sendData(n[i]); //font array starts at 0, ASCII starts at 32. Hence the translation
        sendData(n[i]); //font array starts at 0, ASCII starts at 32. Hence the translation
    }
}

void OzOLED::printString16(const char *String, byte X, byte Y, byte numChar){
    byte count=0;
    while(String[count] && count<numChar){
        printChar16(String[count++], X, Y);
        X += 2;
    }

}

void OzOLED::printChar12a(char C, byte X, byte Y){
    setCursorX2Y(X, Y);
    if(C < 32 || C > 127)        //Ignore unused ASCII characters.
        C='*';        //star - indicate characters that can't be displayed
    unsigned int m = 0;
    unsigned char n[8];

    for ( byte i=0; i<4; i++) {
        m = EnlardeByte2Word(pgm_read_byte(&BasicFont[C-32][2*i]));
        n[2*i] = highByte(m);
        sendData(lowByte(m));
        sendData(lowByte(m));
        m = EnlardeByte2Word(pgm_read_byte(&BasicFont[C-32][2*i+1]));
        sendData(lowByte(m));
        n[2*i+1] = highByte(m);
    }
    setCursorX2Y(X, Y+1);

    for(byte i=0; i<4; i++) {
        sendData(n[2*i]);
        sendData(n[2*i]);
        sendData(n[2*i+1]);
    }
}

void OzOLED::printString12a(const char *String, byte X, byte Y, byte numChar){
    byte count=0;
    while(String[count] && count<numChar){
        printChar12a(String[count++], X, Y);
        X += 3;
    }
}

void OzOLED::printChar12b(char C, byte X, byte Y){
    setCursorX2Y(X, Y);
    if(C < 32 || C > 127)        //Ignore unused ASCII characters.
        C='*';        //star - indicate characters that can't be displayed
    unsigned int m = 0;
    unsigned char n[8];

    for ( byte i=0; i<4; i++) {
        m = EnlardeByte2Word(pgm_read_byte(&BasicFont[C-32][2*i]));
        n[2*i] = highByte(m);
        sendData(lowByte(m));
        m = EnlardeByte2Word(pgm_read_byte(&BasicFont[C-32][2*i+1]));
        sendData(lowByte(m));
        sendData(lowByte(m));
        n[2*i+1] = highByte(m);
    }
    setCursorX2Y(X, Y+1);

    for(byte i=0; i<4; i++) {
        sendData(n[2*i]);
        sendData(n[2*i+1]);
        sendData(n[2*i+1]);
    }
}

void OzOLED::printString12b(const char *String, byte X, byte Y, byte numChar){
    byte count=0;
    while(String[count] && count<numChar){
        printChar12b(String[count++], X, Y);
        X += 3;
    }
}

void OzOLED::setCursorX2Y(byte X, byte Y){
    // Y - 1 unit = 1 page (8 pixel rows)
    // X - 1 unit = 4 pixel columns - half of character cell - for 12-pix fonts

    sendCommand(0x00 + (4*X & 0x0F));         //set column lower address
    sendCommand(0x10 + ((4*X>>4)&0x0F));     //set column higher address
    sendCommand(0xB0 + Y);                     //set page address
}

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

Да, опыт работы с Arduino у меня пока меньше недели, так что на окончательность кода не претендую. В первую очередь не очень представляюю себе всего многообразия моделей и особенностей работы с каждой из них. У меня пока есть только Uno, и ни на чем другом проверить возможности нет.

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

Собственно, вот результат работы:

- первые две строки - исходный шрифт 8х8,

- вторая строка - 16х16,

- третья и четвертая - два варианта 12х16 (обратите внимание на толщину вертикальных линий).

Focus
Offline
Зарегистрирован: 05.04.2015

использовал OLED_I2C, уперся в оперативу. Сейчас использую эту библиотеку https://code.google.com/p/u8glib/ хоть она и мудрёней, но зато мало памяти кушает, раза в 2. Буферы? не неслышал :D незнаю что это такое.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

andriano, если получится ещё и русские буквы прицепить, твоё решение будет очень востребованным.

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

Focus пишет:
использовал OLED_I2C, уперся в оперативу. Сейчас использую эту библиотеку https://code.google.com/p/u8glib/ хоть она и мудрёней, но зато мало памяти кушает, раза в 2. Буферы? не неслышал :D незнаю что это такое.
Библиотека действительно мудреная, да еще и совсем неоткомментированная. Но посмотрю.

Сам практически наверняка пользоваться не буду: в заголовке не обнаружил "#define <Wire.h>", а значит, скорее всего, с другими устройствами на шине I2C эта библиотека дружить не будет.

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

Во-вторых, решение там приведено несколько кривоватое, но следует иметь в виду, что приямого и простого  решения здесь не может быть в принципе. По одной простой причине: в среде Arduino используется кодировка utf-8, т.е. соответствия "один байт - один символ" нет, и для правильной работы требуется достаточно сложный перекодировщик. Сделать его, конечно, можно, но сколько он займет места в памяти (RAM и Flash), сказать затрудняюсь. Совершенно определенно тот перекодировщик, которым я сейчас пользуюсь на PC, в объем памяти Arduino не может поместиться в принципе.

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

По поводу востребованности решения тоже есть некоторые сомнения.

По сути я опубликовал некоторые предложения по двум воросам:

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

- экономная по памяти (хотя и кривоватая по результату) реализация шрифтов большого размера.

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

Focus
Offline
Зарегистрирован: 05.04.2015

andriano пишет:

 в заголовке не обнаружил "#define <Wire.h>", а значит, скорее всего, с другими устройствами на шине I2C эта библиотека дружить не будет.

У меня одновременно работает на одной шине аппаратной 1307+еепром, bmp180 и OLED 128х64

Sloper
Sloper аватар
Offline
Зарегистрирован: 30.03.2015

Вот тут все разжовывается, даже есть элеметы нудизма. 

https://www.youtube.com/watch?v=niA3aPu3-dQ

 

kivik
Offline
Зарегистрирован: 08.07.2015

Всем Доброго дня.

У меня похожий  китайский 128 X 64 OLED LCD из светодиодов дисплей  0.96 "Подключал по схеме

VCC —– +5v  (+5 вольт)

GND —–  GND (земля)

SDA —– pin SDA  (pin A4 для Arduino nano V3)

SCL —–  pin SCL (pin A5 для Arduino nano V3)

Библиотеку использую U8glib.

Проблема как в первом посту, при поступлении питания экран включается на мгновение и темнота пробовал разные примеры ситуация аналогичная . На библиотеке Adafruit было тоже самое. Подскажите что исправить в U8glib.

Focus
Offline
Зарегистрирован: 05.04.2015

kivik пишет:

Всем Доброго дня.

У меня похожий  китайский 128 X 64 OLED LCD из светодиодов дисплей  0.96 "Подключал по схеме

VCC —– +5v  (+5 вольт)

GND —–  GND (земля)

SDA —– pin SDA  (pin A4 для Arduino nano V3)

SCL —–  pin SCL (pin A5 для Arduino nano V3)

Библиотеку использую U8glib.

Проблема как в первом посту, при поступлении питания экран включается на мгновение и темнота пробовал разные примеры ситуация аналогичная . На библиотеке Adafruit было тоже самое. Подскажите что исправить в U8glib.

Там нужно раскоментировать строчку в начале

//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);
 
или первую или вторую, с обоими работает
 
Кстати я у этого же продавца брал этотже экранчик
kivik
Offline
Зарегистрирован: 08.07.2015

Про это я знаю у меня строка иницилизации для  дисплея это:

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);
 
с такой U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST); тоже включается на мгновение. другие не мои
Focus
Offline
Зарегистрирован: 05.04.2015

У меня отлично работает, на I2C висит экран, bmp180, 1307+eeprom безовсяких подтягивающих резисторов. Питаю от 5v (на плате стоит стабилизатор) от 3.3 тоже работало (везде пишут что он на 3.3)

библиотеку брал тут

сканером I2C находится?

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknow error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

 

kivik
Offline
Зарегистрирован: 08.07.2015

Focus
Offline
Зарегистрирован: 05.04.2015

Я бы ещё докучи подтянул I2C резисторами к плюсу http://student-proger.ru/2014/08/vliyanie-nominala-podtyagivayushhih-rezistorov-na-signal-shiny-i2c/, для верности сунул к другой ардуине.

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

kivik
Offline
Зарегистрирован: 08.07.2015

Ардуину другую попробую. А в утиль рано он всетаки что-то выдает, вот на фотик еле поймал. Это я запускал GraphicsTest . Когда запускаю этот тест картинки должны крутится по кругу а у меня секунда даже менее.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

От 3.3 Вольта пробовали запитать?
 

kivik
Offline
Зарегистрирован: 08.07.2015

Спасибо trembo на 3,3В работает, тест запустился и картинки не гаснут.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Просто у вас на плате или отсутствует или пробит стабилизатор.
Скорее всего отсутствует.
Запаяйте.  Там место имеется.
Он только по входам  5 Вольт держит , а по питанию, как вы убедились, всего секунду.

kivik
Offline
Зарегистрирован: 08.07.2015

Я думаю что стабилизаторы не причем, я запитывался от USB ноута. Напряжения на плате проверил 4,98 и 3,29 стабильные. Щас если найду попробую резисторы подтягивающие повесить и запитать от 5В что получится.

kivik
Offline
Зарегистрирован: 08.07.2015

Ребята тысяча извинений проблема была в плохом контакте GND дисплея и GND ардуинки. Сечас работает и на 5В и на 3,3В

Focus
Offline
Зарегистрирован: 05.04.2015

kivik пишет:

Я думаю что стабилизаторы не причем, я запитывался от USB ноута. Напряжения на плате проверил 4,98 и 3,29 стабильные. Щас если найду попробую резисторы подтягивающие повесить и запитать от 5В что получится.

3.29 это где? Вы после стабилизатора на плате меряли?

Дело не в стабильности. Контроллер экрана расчитан на работу от 3.3в, для того чтобы подключать к 5в на плате установлен стабилизатор, который из 5в делает 3.3в. Если его нет или он дохлый - то долго от 5в экран не проработает.

Focus
Offline
Зарегистрирован: 05.04.2015

kivik пишет:

Ребята тысяча извинений проблема была в плохом контакте GND дисплея и GND ардуинки. Сечас работает и на 5В и на 3,3В

Гуд :) А то я ещё парочку собирался заказывать у того продавана.

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

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

Предварительные результаты размещены на настоящем форуме: http://arduino.ru/forum/programmirovanie/kirillitsa-na-displee-ili-chto-ya-delayu-ne-tak#comment-125048

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Очень приятно что бывает такая реклама!

Joiner
Offline
Зарегистрирован: 04.09.2014

Хотел заказать такой экранчик, но отпугнули размеры рабочей области, 21х11 мм. На таком хоть что-то можно рассмотреть? Что-то побоялся заказывать.

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

Под лупой видно :)

Но, честно говоря, мне лично рабочим фонтом представляется только 12х16. Это будет 4 строки по 10 символов. Зато:

- низкое потребление энергии (не нужна подсветка),

- безусловная контрастность,

- нет ограничений по углам,

- нет ограничений на кириллицу,

- при желании (и некотором умении) можно порисовать.

Joiner
Offline
Зарегистрирован: 04.09.2014

andriano пишет:

Под лупой видно :)

Для какого-нибудь миниатюрного устройства наверное неплохо подойдет... Подумаю:)

energokom
Offline
Зарегистрирован: 31.07.2016

andriano пишет:

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

Предварительные результаты размещены на настоящем форуме: http://arduino.ru/forum/programmirovanie/kirillitsa-na-displee-ili-chto-ya-delayu-ne-tak#comment-125048


 

Подскажите пожалуйста как в этой библиотеке размер шрифта увеличить?

/**
 @brief Write character
*/
size_t FaBoOLED_EROLED096::write(uint8_t value) {
  uint8_t i;
  if ( value>=0x20 && value<=0x80 ) {
    _cur_x -= 8;
    if ( _cur_x >= 0 ) {
      setAddress(_cur_y, _cur_x+8, _cur_x+8+8-1);
      writeData( 0x00 );
      writeData( 0x00 );
      for ( i=0; i<5; i++ ) {
        writeData( pgm_read_byte(FONT+(value*5)+i) );
      }
      writeData( 0x00 );
    } else {
      _cur_x = 0;
    }
  }
  return 1;
}

 

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

О какой "этой" библиотеке речь?

maxim0512
Offline
Зарегистрирован: 26.04.2017

Добрый день, прошу помощи специалистов. Есть OLED I2C дисплей 128х64, китайский, адрес 0х3С. При подключение или перезагрузки контролера показывает случайные набор точек, никах символов, просто "сыпь". При этом самое интересное, если выключить и вклють питание может начать начать работать. Таким образом может включится с первого раза, а может с десятого. Пробовал разные библеотеки и разные котролеры (arduino uno, nano. ESP8266-12F. Digispark attiny85). Везде результат один и тот же - может запустится, может нет. Пробовал подключать без подтяжки шины, и с подтяжкой разными резисторами - никакой разницы. Подскажи, пожалуйста, куда копать или как возможно это решить, брак это или нет?

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

поменять дисплей.

maxim0512
Offline
Зарегистрирован: 26.04.2017

Тоесть такое поведение дисплея можно счиать браком? Просто если он запускается то рабоет нормально, и неделю показывал мне часы.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

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

maxim0512
Offline
Зарегистрирован: 26.04.2017

Понятно, спасибо

Duglas
Offline
Зарегистрирован: 22.07.2017

Купил дисплей CRIUS CO-16,

работает только с библиотеками OLED I2c  и U8g2.

C Adafruit_SSD1306 , OzOLED не работает.

Адрес i2c сканером не определяется(при любом питании и с резисторами подтяжки или без)

Anatoliy30_2
Offline
Зарегистрирован: 01.07.2017

Есть потребность подключить два дисплея oled 128x32 по i2c, но они имеют один адрес 0х3С. На плате нет маркировки с пустыми контактами для смены адреса резисторами. Есть ещё способы изменить (подменить) адрес?

Anatoliy30_2
Offline
Зарегистрирован: 01.07.2017

http://ru.aliexpress.com/item/PCF8574-IO-Expansion-Board-I-O-Expander-I2C-Bus-Evaluation-Development-Module/1893663874.html

Этот модуль подменит адрес дисплея, для ардуино?

Focus
Offline
Зарегистрирован: 05.04.2015

Anatoliy30_2 пишет:
Этот модуль подменит адрес дисплея, для ардуино?

Нет, посмотрите на плату, SCL и SDA просто проходят на сквозь и всё. Вам нужно заказать второй экранчик с другим адресом, у меня например есть переключалка (под перемычки напаиванием) для адресов 0x7A и 0x78

yarus
Offline
Зарегистрирован: 17.06.2017

Andriano, не могли бы вы прикрутить к своей библиотеке русский шрифт? Есть большая потребност в его наличии.

Был бы вам очень признателен.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

yarus, так ведь уже (правда без графики, только текст):

http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...

yarus
Offline
Зарегистрирован: 17.06.2017

Tomasina, по поводу вашей библы (http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...)  хочу сказать вот что:

Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...

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

yarus пишет:

Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...

Yarus, не уверен, но по-моему библиотека вообще не поддерживает String.

Во-первых, это не проблема - String легко преобразовывается в char array.

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

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

b707 пишет:

 библиотека вообще не поддерживает String.

IMHO достаточно того, что String поддерживает то, что нужно библиотеке.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

yarus пишет:

Tomasina, по поводу вашей библы (http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...)  хочу сказать вот что:

Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...

Вангую, что никто никогда не читал про метод c_str() класса String, и что он возвращает...

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

А вы пример приведите и неучей станет чуточку меньше ;)

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

Tomasina пишет:
А вы пример приведите и неучей станет чуточку меньше ;)

Не станет. Проверено. :(

Gomez
Offline
Зарегистрирован: 09.09.2017

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

Я использую дисплей 128x32 с Вашей библиотекой, у дисплея пины сбоку и для установки в корпус было бы замечательно перевернуть вывод, тогда бы дисплей встал отлично :)

Я читал, что нужно поменять два параметра "слева направо  – справа налево", "сверху вниз – снизу вверх", но не нахожу этих строк.

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

В последней версии (0.4) для изменения ориентации служат две функции:

  void SetNormalOrientation(); // pins on top 
  void SetTurnedOrientation(); // pins on bottom 
Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

Зачем для одной операции (смена ориентации) делать две разных функции?

Почему не так?

 void setOrientation(TOP); // pins on top 
 void setOrientation(LEFT); // pins on left

или так:

 void setOrientation(0);     // 0 degrees
 void setOrientation(180); // 180 degrees
 void setOrientation(90);   // 90degrees

Вроде даже во фруктовой похоже реализовано.

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

Tomasina пишет:

Зачем для одной операции (смена ориентации) делать две разных функции?

1. Короче код.

2. Быстрее выполняется. (хотя этои не важно)

 

PS. IMHO стоит стремиться не к минимизации количества функций, а к минимизации как усилий при использовании функций, так и сокращению кода самих функций. Впрочем, это дело вкуса.

PPS. Еще объясните, как в Вашем втором варианте должна работать функция setOrientation(45);

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

Код должен быть удобным для пользователя. Помнить разновидности написания SetNormalOrientation, SetTurnedOrientation и т.п. - неудобно.

Короче код? В моем варианте мне общий код видится как раз короче - банальный switch...case

>Еще объясните, как в Вашем втором варианте должна работать функция setOrientation(45);

Опять банальный switch...case. Все, что не соответствует, игнорируется, результат приводится к дефолтному состоянию (45 заменяется на 0).

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

Tomasina пишет:

Опять банальный switch...case. Все, что не соответствует, игнорируется, результат приводится к дефолтному состоянию (45 заменяется на 0). И запоминать придется больше: не только какие значения чему соответствуют, но и какие значения задавать можно, а какие - нельзя.

Ну да, сначала дать пользователю возможность задавать одно из 65536 значений, а потом долго объяснять, что 65534 из них использовать все равно нельзя.

А потом появится пользоватьтель и спросит: "Вот я в цикле меняю ориентацию с приращением один градус, почему у меня сначала ничего не работает, а потом скачком переворачивается?" (Вы почти 5 лет на форуме и еще не встречали таких пользователей? :)

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