OLED Вывод информации
- Войдите на сайт для отправки комментариев
Добрый день.
Вы мне очень помогаете! И вновь приходится обращаться к Вам за помощью по поводу Вывода информации на OLED экран.
Вот такой скетч:
// "Недорогой контроллер на Ардуино нано + TLC5940 + DALLAS-DS18B20" // шести канальный контроллер, 12-bit шим // Комплектация: Arduino nano, RTC-modul, TLC5940, DALLAS-DS18B20. // перед началом компиляции откройте монитор порта в правом верхнем углу окна программы #include <OLED_I2C.h> // Подключение библиотеки для дисплея OLED myOLED(SDA, SCL, 8); extern uint8_t MegaNumbers[]; // Подключение больших шрифтов extern uint8_t SmallFont[]; // Подключение маленьких шрифтов extern uint8_t TinyFont[]; // Подключение мини шрифтов #include "Tlc5940.h" #include <OneWire.h> OneWire ds(5); // Температурный сенсор DALLAS-DS18B20 подключен к D5 #include <DS1307.h> DS1307 rtc(A0, A1); //RTC-модуль подключен к: SDA - > A0, SCL -> A1 Time t; byte tic[6][5]; unsigned long Value[6]; unsigned long Array[6][6]; unsigned long Event[6][3]; float power = 100; // общая мощность освещения [0 - 100] unsigned long time_all; unsigned long last_time_all; byte temp = 0; unsigned int level; // значение уровня канала в цикле периода (рассвет, закат) byte q; byte w; int nm[6]; byte v; byte ventpin = 6; // управление вентилятором осуществляется с D6 int i = 0; unsigned long day_start; unsigned long day_end; byte day_spam = 0; void setup() { Serial.begin ( 115200 ); // Указвать скорость на которой работает Ваш COM-порт Tlc.init(); Tlc.clear(); myOLED.begin(); myOLED.clrScr(); pinMode (ventpin, OUTPUT); rtc.halt(false); /* MONDEY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY Три строчки ниже необходимо раскомментировать (убрать двойную дробь) при стартовой загрузки программы. Сразу после первой загрузки, нужно закомментировать данные строки и обращаться к этой процедуре в случае сбоя в работе часов. RTC-модуль запомнит время. */ // rtc.setDOW(TUESDAY); // изменить день недели. примеры указаны на четыре строчки выше // rtc.setTime(17, 04, 0); // время // rtc.setDate(13, 10, 2015); // дата // Настройки светильника: <время восхода>, <продолжительность рассвета>, <мощность канала в течении "дня">, <время заката>, <продолжительность заката> // первый канал Array[0][0] = 540; // начало рассвета первого канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[0][1] = 541; // конец рассвета первого канала. например: 11:15 записывается как <675> (в минутах) Array[0][2] = 1050; // начало заката первого канала. например: 20:50 записывается как <1250> (в минутах) Array[0][3] = 1080; // окончание заката первого канала. например: 21:50 записывается как <1310> (в минутах) Array[0][4] = 100; // мощность первого канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[0][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // второй канал Array[1][0] = 540; // начало рассвета второго канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[1][1] = 545; // конец рассвета второго канала. например: 11:15 записывается как <675> (в минутах) Array[1][2] = 1050; // начало заката второго канала. например: 20:50 записывается как <1250> (в минутах) Array[1][3] = 1080; // окончание заката второго канала. например: 21:50 записывается как <1310> (в минутах) Array[1][4] = 80; // мощность второго канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[1][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // третий канал Array[2][0] = 540; // начало рассвета тертьего канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[2][1] = 550; // конец рассвета тертьего канала. например: 11:15 записывается как <675> (в минутах) Array[2][2] = 1050; // начало заката тертьего канала. например: 20:50 записывается как <1250> (в минутах) Array[2][3] = 1080; // окончание заката тертьего канала. например: 21:50 записывается как <1310> (в минутах) Array[2][4] = 80; // мощность тертьего канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[2][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // четвертый канал Array[3][0] = 540; // начало рассвета четвертого канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[3][1] = 555; // конец рассвета четвертого канала. например: 11:15 записывается как <675> (в минутах) Array[3][2] = 1050; // начало заката четвертого канала. например: 20:50 записывается как <1250> (в минутах) Array[3][3] = 1080; // окончание заката четвертого канала. например: 21:50 записывается как <1310> (в минутах) Array[3][4] = 80; // мощность четвертого канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[3][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // пятый канал Array[4][0] = 540; // начало рассвета пятого канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[4][1] = 560; // конец рассвета пятого канала. например: 11:15 записывается как <675> (в минутах) Array[4][2] = 1050; // начало заката пятого канала. например: 20:50 записывается как <1250> (в минутах) Array[4][3] = 1080; // окончание заката пятого канала. например: 21:50 записывается как <1310> (в минутах) Array[4][4] = 100; // мощность пятого канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[4][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // шестой канал Array[5][0] = 540; // начало рассвета шестого канала в минутах. например: 10:00 записывается как <600> (в минутах) Array[5][1] = 570; // конец рассвета шестого канала. например: 11:15 записывается как <675> (в минутах) Array[5][2] = 1050; // начало заката шестого канала. например: 20:50 записывается как <1250> (в минутах) Array[5][3] = 1080; // окончание заката шестого канала. например: 21:50 записывается как <1310> (в минутах) Array[5][4] = 100; // мощность шестого канала в процентах в течении "дня" (в процентах). не может быть больше 100 Array[5][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика // параметры каналов nm[0] = 395; nm[1] = 420; nm[2] = 452; nm[3] = 475; nm[4] = 495; nm[5] = 6500; // Перевод массива в секунды for (q=0; q<6; q++) { for (w=0; w<4; w++) { Array[q][w] = Array[q][w] * 60; } } // Определение параметров экрана для перехода в screen saver day_start = Array[0][0]; for (q=1; q<6; q++) { day_start = min (day_start, Array[q][0]); } day_start = day_start - 60; //screen saver отключается за 60 секунд до рассвета day_end = Array[0][3]; for (q=1; q<6; q++) { day_end = max (day_end, Array[q][3]); } day_end = day_end + 60; //screen saver включается после 60 секунд от заката // Сброс суточного массива for (q=0; q<6; q++) { for (w=0; w<5; w++) { tic[q][w] = 0; } } // Вывод проверочной стартовой таблицы Serial.println ( F("" ));Serial.println ( F("" )); Serial.print ( F(" Time: " )); Serial.print ( rtc.getTimeStr() ); Serial.println ( F(" <- Check this after reset." ));Serial.println ( F("" )); Serial.println ( F(" Chanal : Sanrise : Day : Sanset : Night : Led chanal: Inverse" )); for (q=0; q<6; q++) { Serial.print ( F(" PWM" )); Serial.print ( q+1 ); for (w=0; w<5; w++) { Serial.print ( F(" : " )); if (w < 4) { if ( ( Array[q][w]/3600 ) < 10) {Serial.print ( F("0" )); Serial.print ( Array[q][w]/3600 ); } else {Serial.print ( Array[q][w]/3600 );} Serial.print ( F(":" )); if ((( Array[q][w]-((Array[q][w]/3600)*3600))/60) < 10) {Serial.print ( F("0" ));Serial.print (( Array[q][w]-((Array[q][w]/3600)*3600))/60 ); } else {Serial.print (( Array[q][w]-((Array[q][w]/3600)*3600))/60 );} } else { if (Array[q][w] < 100) {Serial.print ( F(" "));} Serial.print ( Array[q][w]);Serial.print ( F("%"));Serial.print ( F(" : ")); Serial.print ( Array[q][w+1]); } } Serial.println ( F("" )); } Serial.println ( F("-------------------------------------------------" )); // Проверка корректности ввода исходных данных for (q=0; q<6; q++) {if (Array[q][4] >= 86400) {Array[q][4] = 86399; Serial.print ( F("Error, check PWM" )); Serial.print ( q+1 ); Serial.println ( F(", fixed the end of the sunset to 24:00" ));}} for (q=0; q<6; q++) {if (Array[q][5] >= 101) {Array[q][5] = 100; Serial.print ( F("Error, check PWM" )); Serial.print ( q+1 ); Serial.println ( F(", fixed the power led to 100%" )); }} for (q=0; q<6; q++) { for (w=0; w<3; w++) { if ( Array[q][w] > Array[q][w+1] ) {Serial.print ( F("Error, check PWM" )); Serial.print ( q+1 ); Serial.println ( F(", not continuity sanrise and sanset. Controller will not work correctly. Check setup. " )); } } } Serial.print ( F(" All powerful LEDs: " )); Serial.print ( power ); Serial.println ( F("%" )); Serial.println ( F(" In service. OK." )); // Изменение мощности из процентов в значение for (q=0; q<6; q++) { Value[q] = map (Array[q][4], 0, 100, 0, 4095) * (power/ 100); } } void loop() { // Константы температуры float tmin = 26.00; // минитальное значение на датчике, при достижении которого запускается вентилятор. Указывается значение в градусах. Например: "32", означает 32градуса цельсия float tmax = 36.00; // максимальное значение на датчике, служит для плавного увеличения скорости вращения вентилятора. Указывается значение в градусах. Например: "36", означает 36градуса цельсия. На превышающих значениях вентилятор работает на 100% мощности // Блок программы работающий с температурным датчиком и вентилятором byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius; ds.search(addr); ds.reset(); ds.select(addr); ds.write(0x44, 1); ds.reset(); present = ds.reset(); ds.select(addr); ds.write(0xBE); for ( i = 0; i < 9; i++) { data[i] = ds.read(); } int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; if (temp == 0) { Serial.print(F(" Temperature = ")); Serial.print(celsius); Serial.println(F(" Celsius \n ")); temp = 1;} if ( tmin > celsius )analogWrite (ventpin, 0); if ( tmin <= celsius && tmax >= celsius ) analogWrite (ventpin, map(celsius, tmin , tmax, 0, 255)); if ( tmax < celsius) analogWrite (ventpin,255); // конец блока температуры String stringOne = rtc.getTimeStr(); t = rtc.getTime(); int long h = t.hour; int long m = t.min; int long s = t.sec; time_all = ( (h * 3600)+(m * 60)+ s ); // Контроллер for (q=0; q<6; q++) { if (time_all >= 0 && time_all < Array[q][0] && tic[q][0] == 0) { if (Array[q][5]==0)Tlc.set (q, 0); if (Array[q][5]==1)Tlc.set (q, 4095); tic[q][0] = 1; Serial.print ( rtc.getTimeStr() );Serial.print ( F(" PWM:" ));Serial.print ( q+1 ); Serial.println ( F(" - mon" )); } if (time_all >= Array[q][0] && time_all <= Array[q][1] ) { if (tic[q][1] == 0){Event[q][0] = (time_all - Array[q][0])*1000; Event[q][1] = ((Array[q][1]-Array[q][0])*1000); Event[q][2] = millis(); Serial.print ( rtc.getTimeStr() );Serial.print ( F(" PWM:" ));Serial.print ( q+1 ); Serial.println ( F(" - on" )); tic[q][1] = 1;} level = (((float)millis() - Event[q][2]+Event[q][0])*Value[q])/(Event[q][1]); if(level <= 0) level = 0; if(level >= Value[q]) level = Value[q]; if (Array[q][5]==0)Tlc.set (q, level); if (Array[q][5]==1)Tlc.set (q, 4095-level); Serial.println ( level ); } if (time_all > Array[q][1] && time_all < Array[q][2] && tic[q][2] == 0) { if (Array[q][5]==0)Tlc.set (q, Value[q]); if (Array[q][5]==1)Tlc.set (q, 4095-Value[q]); tic[q][2] = 1 ; Serial.print ( rtc.getTimeStr() );Serial.print ( F(" PWM:" ));Serial.print ( q+1 ); Serial.println ( F(" - day " )); } if (time_all >= Array[q][2] && time_all <= Array[q][3] ) { if (tic[q][3] == 0){ Event[q][0] = (time_all - Array[q][2])*1000; Event[q][1] = ((Array[q][3]-Array[q][2])*1000); Event[q][2] = millis(); Serial.print ( rtc.getTimeStr() );Serial.print ( F(" PWM:" ));Serial.print ( q+1 ); Serial.println ( F(" - off" )); tic[q][3] = 1;} level = (((float)millis() - Event[q][2]+Event[q][0])*Value[q])/(Event[q][1]); if(level <= 0) level = 0; if(level >= Value[q]) level = Value[q]; if (Array[q][5]==0)Tlc.set (q, Value[q]-level); // Закат сделан по принципу рассвета. if (Array[q][5]==1)Tlc.set (q, 4095-Value[q]+level); // Разница в этих двух строках. Serial.println ( Value[q]-level ); } if (time_all > Array[q][3] && time_all <= 86399 && tic[q][4] == 0) { if (Array[q][5]==0)Tlc.set (q, 0); if (Array[q][5]==1)Tlc.set (q, 4095); tic[q][4] = 1 ; Serial.print ( rtc.getTimeStr() );Serial.print ( F(" PWM:" ));Serial.print ( q+1 ); Serial.println ( F(" - nig" )); } } Tlc.update(); // Сброс состояния контроллера на новый день. if (time_all < last_time_all) { // Сброс суточного массива for (q=0; q<6; q++) { for (w=0; w<5; w++) { tic[q][w] = 0; } } } // Блок вывода информации на экран if ( time_all - last_time_all == 1) { if ( time_all >= day_start && time_all <= day_end) { myOLED.clrScr(); myOLED.setBrightness(100); myOLED.setFont(SmallFont); myOLED.print(rtc.getTimeStr(), 0, 0); myOLED.print( "t:", 88, 0); myOLED.print(String(int (celsius)), 95, 0); myOLED.setFont(TinyFont); myOLED.print(String(int (power)), 0, 10); if (power == 100)myOLED.print("%", 12, 10); else myOLED.print("%", 10, 10); myOLED.print(String(int (power/2)), 0, 33); myOLED.print("%", 10, 33); myOLED.print("fan:", 55, 1); v = map(celsius, tmin , tmax, 0, 100); if (v >= 0 && v <= 100) { myOLED.print(String(int (v)), 72, 1); if (v <= 9) myOLED.print("%", 76, 1); if (v >= 10 && v <= 99) myOLED.print("%", 80, 1); if (v == 100) myOLED.print("%", 85, 1);} else myOLED.print("off", 72, 1); for (q=0; q<6; q++) { myOLED.drawLine(((q+1)*18)-1, 11, ((q+1)*18)+1, 11); // разметка myOLED.drawLine(((q+1)*18)-1, 33, ((q+1)*18)+1, 33); // разметка myOLED.drawLine(((q+1)*18), 55, ((q+1)*18), 63); // разметка myOLED.print(String(nm[q]), 4+((q+1)*18), 58); // подписи nm if (time_all >= Array[q][0] && time_all <= Array[q][1]) { level = ((time_all - Array[q][0]) * ((Array[q][4]*44)/100)) / (Array[q][1] - Array[q][0]);} if (time_all >= Array[q][1] && time_all <= Array[q][2]) { level = ((Array[q][4]*44)/100);} if (time_all >= Array[q][2] && time_all <= Array[q][3]) { level = (((Array[q][4]*44)/100) * (Array[q][3] - time_all)) / (Array[q][3] - Array[q][2]);} if (time_all <= Array[q][0] || time_all >= Array[q][3]) { level = 0;} for (w=0; w<8; w++) { myOLED.drawLine(((q+1)*18)+w+5, 55 - level, ((q+1)*18)+w+5, 55); } } } else { // Ночные настройки myOLED.clrScr(); myOLED.setBrightness(0); myOLED.setFont(MegaNumbers); myOLED.print(stringOne.substring(0, 2), 4, 12); switch (day_spam) { case 0: myOLED.print("/", 51, 12); day_spam = 1; break; case 1: myOLED.print("-", 51, 12); day_spam = 0; break;} myOLED.print(stringOne.substring(3, 5), 75, 12); } myOLED.update(); } last_time_all = time_all; }
Вот это выдает после компилляции:
По сути вопрос только по выводу информации на экран: с 320строки.
Программа в принципе работает. Но в процессе расширения выводимой информации, ее часть почему то перестает выводиться. Т.е. изначально она выводилась, а потом в процессе написания еще строк почему то пропадала.
Вот тут, где обведено красным была информации, но она теперь не выводится.
Заметил, что информация не выводится в таких выражениях:
myOLED.print(String(int (celsius)), 95, 0);
myOLED.print(stringOne.substring(3, 5), 75, 12);
А в таких выводится без проблем:
myOLED.print("fan:", 55, 1);
Прошу, подскажите, с чем это может быть связано? Возможно с отсутсвием памяти, т.к. если сделать отдельный скетч под вывод, он работает без проблем. Как сделать так, чтоб вывод работал?
Ну, не пишет со String понятно почему - не хватает памяти для создания String.
Попробуйте хоть немного экономить память. Ну, например, не пихать String везде куда не попадя (а лучше вообще без него обойтись). И там много по программе мест, где можно сэкономить. например, так ли обязательно массиву Array иметь тип long. Вы уверены, что он в int не помещается? Особенно, если его арифметику аккуратно прописать?
Вы очень увлекаетесь глобальными переменными. Например, зачем time_all быть глобальной, если она используется только в одной функции.
Внутри функций можно управлять выделением памяти для локальных переменных при помощи фигурных скобок так, чтобы более ненужные переменные не занимали память, а освобождали её для других переменных.
В общем, надо садиться и оптимизировать использование памяти.
Кроме того, ровно половину всей доступной памяти у Вас кушает массив scrbuf[1024] в библиотеке OLED_I2C, но от него избавиться не так легко - нужно использовать другую библиотеку.
18-я строка.
ЗАЧЕМ ТАК ДЕЛАТЬ?!
Спасибо большое.
Действительно, освобождение памяти все решило.
"Век учись, век живи, все равно дураком помрешь..." (с)
ЧТо бы сэкономить память (dinamic memory), очень помагает макрос F() в строках.
Например:
Вместо: