помогите разобраться в коде для oled дисплея
- Войдите на сайт для отправки комментариев
Ср, 18/01/2017 - 20:40
Здравствуйте. Делаю для себя некое устройство с oled дисплеем и батарейным питанием. На дисплее надо отображать заряд, ну как в телефоне. Возникла маленькая проблемка с массивами. Если раскоментировать сторки и убрать ненужные с _batdisp то все работает. Захотел сделать через указатель на массивы - не получается, выводиться какая то фигня. Как поправить код, чтобы работало. Сразу оговорюсь Ардуино - хобби, поэтому язык знаю не очень.
#include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <SPI.h> #include <Wire.h> #define OLED_MOSI 9 #define OLED_CLK 10 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 8 #define A1_PIN 1 // акб Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); #if (SSD1306_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif float vcc=0.00; int vb; char _batdisp; static const unsigned char PROGMEM bat2 []= { //24x16 66% батарейки 0,0,0, 63,255,255, 63,255,255, 48,0,3, 48,30,123, 240,30,123, 240,30,123, 240,30,123, 240,30,123, 240,30,123, 240,30,123, 48,30,123, 48,0,3, 63,255,255, 63,255,255, 0,0,0 }; static const unsigned char PROGMEM bat3 []= { //24x16 100% батарейки 0,0,0, 63,255,255, 63,255,255, 48,0,3, 55,158,123, 247,158,123, 247,158,123, 247,158,123, 247,158,123, 247,158,123, 247,158,123, 55,158,123, 48,0,3, 63,255,255, 63,255,255, 0,0,0 }; static const unsigned char PROGMEM bat1 []= { //24x16 33% батарейки 0,0,0, 63,255,255, 63,255,255, 48,0,3, 48,0,123, 240,0,123, 240,0,123, 240,0,123, 240,0,123, 240,0,123, 240,0,123, 48,0,123, 48,0,3, 63,255,255, 63,255,255, 0,0,0 }; static const unsigned char PROGMEM bat0 []= { //24x16 0% батарейки 0,0,0, 63,255,255, 63,255,255, 48,0,3, 48,0,3, 240,0,3, 240,0,3, 240,0,3, 240,0,3, 240,0,3, 240,0,3, 48,0,3, 48,0,3, 63,255,255, 63,255,255, 0,0,0 }; void disp_on(){ //функция вкл дисплея digitalWrite(7,HIGH); //подаем питание на дисплей delay(1); display.begin(SSD1306_SWITCHCAPVCC); display.clearDisplay(); delay(5); } float vbat(){ //функция определения и отображения напряжения батареи vb = analogRead(A1_PIN); vcc = (vb* 5.00) / 1023.0; if(vcc>=3.4) { _batdisp=&bat3; //display.drawBitmap(100,0,bat3,24,16,WHITE); } if(vcc>=3.2 && vcc<3.4 ) { _batdisp=&bat2; // display.drawBitmap(100,0,bat2,24,16,WHITE); } if(vcc>=3.0 && vcc<3.2 ) { _batdisp=&bat1; // display.drawBitmap(100,0,bat1,24,16,WHITE); } if(vcc<3.0 ) { _batdisp=&bat0; // display.drawBitmap(100,0,bat0,24,16,WHITE); } return _batdisp; } void setup() { pinMode(7, OUTPUT); disp_on(); } void loop() { display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(6,1); // vbat(); display.drawBitmap(100,0,_batdisp,24,16,WHITE); display.display(); }
А Вы не думали что батарейку можно линиями нарисовать, а процент заряженности выводить с помощью закрашенного прямоугольника? Так и гралаций больше можно полчить. Или нарисовать батарейку, а внутри тупа текстом 15% например... имхо. Или {20%].
Линиями попробую. Я рисую батарейку, а в ней есть 3 зоны, которые закрашиваються в зависимости от заряда. Никаких процентов мне не надо.
Ну зоны тоже маленькими прямругольниками можно. Хотя дело хозяйское.
Рисую вот такую.
Так и понял, но чем забивать память "BITMAP`ами" мне кажеться проще генерировать изобраение батареи из примитивов.
Так и понял, но чем забивать память "BITMAP`ами" мне кажеться проще генерировать изобраение батареи из примитивов.
Это уж вопрос художественный.
А технический - при извлечении из PROGMEM надо использовать функции расчитаные именно на PROGMEM. Не факт что в вашей либе оно есть, проверять надо.
Кроме того, непонятна политика использования _batdisp. Если она глобальная - зачем возвращать её из функции, если возвращается из функции - почему не использовать это и зачем она глобальная.
Так и понял, но чем забивать память "BITMAP`ами" мне кажеться проще генерировать изобраение батареи из примитивов.
Я почему то думал наоборот. Картинка готова, указал какую и на печать.... Сидел сейчас читал про progmem - как то все размыто там. Будем изучать дальше, а пока вернул функцию выбора обратно.
Это уж вопрос художественный.
А технический - при извлечении из PROGMEM надо использовать функции расчитаные именно на PROGMEM. Не факт что в вашей либе оно есть, проверять надо.
Кроме того, непонятна политика использования _batdisp. Если она глобальная - зачем возвращать её из функции, если возвращается из функции - почему не использовать это и зачем она глобальная.
Пытался по разному указывать на массивы с картинками. Я же говорю неочень я в си. Может можно копировать нужный массив в batdisp?
:))) сделать индикатор заряда.... чтоб этот заряд садить :))))))))))
Может можно копировать нужный массив в batdisp?
Можна конечно и копировать. Функции для работы PROGMEM например здесь - http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
Копировать оно конечно послабей будет вариант, и время и место займет. Но если в либке нет нужного, и сами не допишите - остается копировать.
Спасибо за справочник. Поизучал про копирование через memccpy - долго все это, не целесообразно выделять еще памяти для временного массива. Вобщем удалю все что связано с batdisp и оставлю как было раньше.
На дисплее надо отображать заряд, ну как в телефоне.
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafru...
Там в примере OledSymbolTest показано как это можно сделать.
Я думаю, что тут основная проблема в том, что вы объявляете возвращаемое значение функции как float:
float
vbat() и пытаетесь в нее вернуть массив:
return
_batdisp;
ага. я сразу не смотрел весь код . А там мрак. Сама _batdisp это char, ей присваиваются указатели а возвращвется float и передается в display.drawBitmap которая указатель на буфер ждет. Оно вобще компилируется?
передается в display.drawBitmap которая указатель на буфер ждет.
Спасибо за наводку, я все думал, что же тут еще не так)) исправил тип переменной с char на int и все заработало!
Вот код для ТС, только я его под свой дисплей от Нокии 5110 адаптировал, но думаю, что разберется))
А вот у меня еще вопрос по этой теме: зачем надо было делать это _batdisp=&bat3;? Почему просто каждый раз не использовать display.drawBitmap(0,0,bat3,24,16, 1);? Это как то сказывается на расход батареи?
Спасибо всем за участие. Я же говорю что не очень... В коде разберусь, хотя по факту надо тип переменной поменять только.
А вот у меня еще вопрос по этой теме: зачем надо было делать это _batdisp=&bat3;? Почему просто каждый раз не использовать display.drawBitmap(0,0,bat3,24,16, 1);? Это как то сказывается на расход батареи?
Тогда картинка батарейки будет всегда заряжена, независимо от напряжения на аналоговом входе.
Ну и зашибись! Вечнозаряженый;)
Я так думаю, neyasbltb_88 имел ввиду что вместо _batdisp=... стр. 136,141,146 и 151 предпочтительней оставить вызовы, закоментированые на следующих строках. Дак нет, не лучше. Это и называется оптимизация. Т.к. организация вызова display.drawBitmap довольно ресурсоемка, то лучше вызывать его только раз передавая указатель через переменную, как приведено в примере.
Но если уж писать про оптимизацию, то надо и про
float
vcc;
заметить. Нечего его в форме с плавающей запятой держать. Обязательно на фиксированую перейти. Самое верное - в форме как с analogRead прийдет - так и оставлять, а значения границ диапазонов определить константными выражениями, так чтоб в тексте проги задавать в миливольтах, а компилятор пересчитывал их в значения соответствующие получаемому с analogRead. Так и код короткий и человеку в программе удобно.