Преодоление проблем с экраном 0.96 128X64 OLED LCD I2C SSD1306
- Войдите на сайт для отправки комментариев
Преодоление проблем с экраном 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, и ни на чем другом проверить возможности нет.
Собственно, вот результат работы:
- первые две строки - исходный шрифт 8х8,
- вторая строка - 16х16,
- третья и четвертая - два варианта 12х16 (обратите внимание на толщину вертикальных линий).
использовал OLED_I2C, уперся в оперативу. Сейчас использую эту библиотеку https://code.google.com/p/u8glib/ хоть она и мудрёней, но зато мало памяти кушает, раза в 2. Буферы? не неслышал :D незнаю что это такое.
andriano, если получится ещё и русские буквы прицепить, твоё решение будет очень востребованным.
Сам практически наверняка пользоваться не буду: в заголовке не обнаружил "#define <Wire.h>", а значит, скорее всего, с другими устройствами на шине I2C эта библиотека дружить не будет.
Во-вторых, решение там приведено несколько кривоватое, но следует иметь в виду, что приямого и простого решения здесь не может быть в принципе. По одной простой причине: в среде Arduino используется кодировка utf-8, т.е. соответствия "один байт - один символ" нет, и для правильной работы требуется достаточно сложный перекодировщик. Сделать его, конечно, можно, но сколько он займет места в памяти (RAM и Flash), сказать затрудняюсь. Совершенно определенно тот перекодировщик, которым я сейчас пользуюсь на PC, в объем памяти Arduino не может поместиться в принципе.
Попробовать, конечно, можно, но основная проблема (для меня) состоит в том, что меня отсутствие кириллицы совершенно не напрягает.
По поводу востребованности решения тоже есть некоторые сомнения.
По сути я опубликовал некоторые предложения по двум воросам:
- программная борьба с аппаратными багами конкретного устройства - может быть интересно только владельцам аналогичного устройства с аналогичными багами,
- экономная по памяти (хотя и кривоватая по результату) реализация шрифтов большого размера.
Расширение набора символов ни к тому ни к другому не относятся. Решение этого конкретного вопроса, конечно, предложить можно, но боюсь, оно не будет являться законченным, т.е. его придется самостоятельно интегрировать в каждую используемую библиотеку работы с экраном.
в заголовке не обнаружил "#define <Wire.h>", а значит, скорее всего, с другими устройствами на шине I2C эта библиотека дружить не будет.
У меня одновременно работает на одной шине аппаратной 1307+еепром, bmp180 и OLED 128х64
Вот тут все разжовывается, даже есть элеметы нудизма.
https://www.youtube.com/watch?v=niA3aPu3-dQ
Всем Доброго дня.
У меня похожий китайский 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.
Всем Доброго дня.
У меня похожий китайский 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.
Там нужно раскоментировать строчку в начале
Про это я знаю у меня строка иницилизации для дисплея это:
У меня отлично работает, на I2C висит экран, bmp180, 1307+eeprom безовсяких подтягивающих резисторов. Питаю от 5v (на плате стоит стабилизатор) от 3.3 тоже работало (везде пишут что он на 3.3)
библиотеку брал тут
сканером I2C находится?
Я бы ещё докучи подтянул I2C резисторами к плюсу http://student-proger.ru/2014/08/vliyanie-nominala-podtyagivayushhih-rezistorov-na-signal-shiny-i2c/, для верности сунул к другой ардуине.
Если ничего неизменится - писал бы китайцу, ну или дисплейчик в утиль
Ардуину другую попробую. А в утиль рано он всетаки что-то выдает, вот на фотик еле поймал. Это я запускал GraphicsTest . Когда запускаю этот тест картинки должны крутится по кругу а у меня секунда даже менее.
От 3.3 Вольта пробовали запитать?
Спасибо trembo на 3,3В работает, тест запустился и картинки не гаснут.
Просто у вас на плате или отсутствует или пробит стабилизатор.
Скорее всего отсутствует.
Запаяйте. Там место имеется.
Он только по входам 5 Вольт держит , а по питанию, как вы убедились, всего секунду.
Я думаю что стабилизаторы не причем, я запитывался от USB ноута. Напряжения на плате проверил 4,98 и 3,29 стабильные. Щас если найду попробую резисторы подтягивающие повесить и запитать от 5В что получится.
Ребята тысяча извинений проблема была в плохом контакте GND дисплея и GND ардуинки. Сечас работает и на 5В и на 3,3В
Я думаю что стабилизаторы не причем, я запитывался от USB ноута. Напряжения на плате проверил 4,98 и 3,29 стабильные. Щас если найду попробую резисторы подтягивающие повесить и запитать от 5В что получится.
3.29 это где? Вы после стабилизатора на плате меряли?
Дело не в стабильности. Контроллер экрана расчитан на работу от 3.3в, для того чтобы подключать к 5в на плате установлен стабилизатор, который из 5в делает 3.3в. Если его нет или он дохлый - то долго от 5в экран не проработает.
Ребята тысяча извинений проблема была в плохом контакте GND дисплея и GND ардуинки. Сечас работает и на 5В и на 3,3В
Гуд :) А то я ещё парочку собирался заказывать у того продавана.
Не то чтобы на правах рекламы, но к сведению: как раз для этого дисплея сейчас делаю библиотку.
Предварительные результаты размещены на настоящем форуме: http://arduino.ru/forum/programmirovanie/kirillitsa-na-displee-ili-chto-ya-delayu-ne-tak#comment-125048
Очень приятно что бывает такая реклама!
Хотел заказать такой экранчик, но отпугнули размеры рабочей области, 21х11 мм. На таком хоть что-то можно рассмотреть? Что-то побоялся заказывать.
Под лупой видно :)
Но, честно говоря, мне лично рабочим фонтом представляется только 12х16. Это будет 4 строки по 10 символов. Зато:
- низкое потребление энергии (не нужна подсветка),
- безусловная контрастность,
- нет ограничений по углам,
- нет ограничений на кириллицу,
- при желании (и некотором умении) можно порисовать.
Под лупой видно :)
Для какого-нибудь миниатюрного устройства наверное неплохо подойдет... Подумаю:)
Не то чтобы на правах рекламы, но к сведению: как раз для этого дисплея сейчас делаю библиотку.
Предварительные результаты размещены на настоящем форуме: http://arduino.ru/forum/programmirovanie/kirillitsa-na-displee-ili-chto-ya-delayu-ne-tak#comment-125048
Подскажите пожалуйста как в этой библиотеке размер шрифта увеличить?
О какой "этой" библиотеке речь?
Добрый день, прошу помощи специалистов. Есть OLED I2C дисплей 128х64, китайский, адрес 0х3С. При подключение или перезагрузки контролера показывает случайные набор точек, никах символов, просто "сыпь". При этом самое интересное, если выключить и вклють питание может начать начать работать. Таким образом может включится с первого раза, а может с десятого. Пробовал разные библеотеки и разные котролеры (arduino uno, nano. ESP8266-12F. Digispark attiny85). Везде результат один и тот же - может запустится, может нет. Пробовал подключать без подтяжки шины, и с подтяжкой разными резисторами - никакой разницы. Подскажи, пожалуйста, куда копать или как возможно это решить, брак это или нет?
поменять дисплей.
Тоесть такое поведение дисплея можно счиать браком? Просто если он запускается то рабоет нормально, и неделю показывал мне часы.
если второй дисплей будет работать нормально, проблема в дисплее, если также, то косяки у тебя в схемотенике.
Понятно, спасибо
Купил дисплей CRIUS CO-16,
работает только с библиотеками OLED I2c и U8g2.
C Adafruit_SSD1306 , OzOLED не работает.
Адрес i2c сканером не определяется(при любом питании и с резисторами подтяжки или без)
Есть потребность подключить два дисплея oled 128x32 по i2c, но они имеют один адрес 0х3С. На плате нет маркировки с пустыми контактами для смены адреса резисторами. Есть ещё способы изменить (подменить) адрес?
http://ru.aliexpress.com/item/PCF8574-IO-Expansion-Board-I-O-Expander-I2C-Bus-Evaluation-Development-Module/1893663874.html
Этот модуль подменит адрес дисплея, для ардуино?
Нет, посмотрите на плату, SCL и SDA просто проходят на сквозь и всё. Вам нужно заказать второй экранчик с другим адресом, у меня например есть переключалка (под перемычки напаиванием) для адресов 0x7A и 0x78
Andriano, не могли бы вы прикрутить к своей библиотеке русский шрифт? Есть большая потребност в его наличии.
Был бы вам очень признателен.
yarus, так ведь уже (правда без графики, только текст):
http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...
Tomasina, по поводу вашей библы (http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...) хочу сказать вот что:
Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...
Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...
Yarus, не уверен, но по-моему библиотека вообще не поддерживает String.
Во-первых, это не проблема - String легко преобразовывается в char array.
Во-вторых, как уже неоднократно отмечалось. использование String в ардуино есть плохой стиль программирования, советую избавлятся от String в своих проектах.
библиотека вообще не поддерживает String.
IMHO достаточно того, что String поддерживает то, что нужно библиотеке.
Tomasina, по поводу вашей библы (http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...) хочу сказать вот что:
Либа классная, но у меня кое-что не получилось, а именно, не удается вывести переменную типа String - выдает ошибку...
Вангую, что никто никогда не читал про метод c_str() класса String, и что он возвращает...
А вы пример приведите и неучей станет чуточку меньше ;)
Не станет. Проверено. :(
andriano, не могли бы Вы подсказать, как можно в Вашей библиотеке повернуть отображение дисплея на 180 градусов?
Я использую дисплей 128x32 с Вашей библиотекой, у дисплея пины сбоку и для установки в корпус было бы замечательно перевернуть вывод, тогда бы дисплей встал отлично :)
Я читал, что нужно поменять два параметра "слева направо – справа налево", "сверху вниз – снизу вверх", но не нахожу этих строк.
В последней версии (0.4) для изменения ориентации служат две функции:
Зачем для одной операции (смена ориентации) делать две разных функции?
Почему не так?
или так:
Вроде даже во фруктовой похоже реализовано.
Зачем для одной операции (смена ориентации) делать две разных функции?
1. Короче код.
2. Быстрее выполняется. (хотя этои не важно)
PS. IMHO стоит стремиться не к минимизации количества функций, а к минимизации как усилий при использовании функций, так и сокращению кода самих функций. Впрочем, это дело вкуса.
PPS. Еще объясните, как в Вашем втором варианте должна работать функция setOrientation(45);
Код должен быть удобным для пользователя. Помнить разновидности написания SetNormalOrientation, SetTurnedOrientation и т.п. - неудобно.
Короче код? В моем варианте мне общий код видится как раз короче - банальный switch...case
>Еще объясните, как в Вашем втором варианте должна работать функция setOrientation(45);
Опять банальный switch...case. Все, что не соответствует, игнорируется, результат приводится к дефолтному состоянию (45 заменяется на 0).
Опять банальный switch...case. Все, что не соответствует, игнорируется, результат приводится к дефолтному состоянию (45 заменяется на 0). И запоминать придется больше: не только какие значения чему соответствуют, но и какие значения задавать можно, а какие - нельзя.
Ну да, сначала дать пользователю возможность задавать одно из 65536 значений, а потом долго объяснять, что 65534 из них использовать все равно нельзя.
А потом появится пользоватьтель и спросит: "Вот я в цикле меняю ориентацию с приращением один градус, почему у меня сначала ничего не работает, а потом скачком переворачивается?" (Вы почти 5 лет на форуме и еще не встречали таких пользователей? :)
Интерфейс библиотеки должен быть простой, понятный, и по возможности не допускающий неправильного использования.