Передача данных по UART при активном TVout
- Войдите на сайт для отправки комментариев
Который день бьюсь над проблемой передачи данных от одного МК другому. Вернее на данный момент застрял на передаче данных через "монитор порта" к Mini pro.
Эти "извращения" связаны с использованием библиотеки (и функции) TVout. К сожалению без ТВ не могу.
Serial не работает (почему - не знаю, видимо конфликтует с TVout), поэтому использую pollserial.
На данный момент застрял на разборке данных. Код был написан после изучения нескольких примеров и чтения разных тем.
Вот кусок, который отвечает за чтение и обработку (добавлены строки для "обратной связи"):
void loop() { if (pserial.available() > 0) { //если есть данные в буфере delay(3); myChar = (char)pserial.read(); //считываем байт pserial.print(myChar); //отправляем в порт для контроля if (myChar == 'F') { stringComplete = true;} //если пришло окончание строки, то ставим метку if (myChar == 'A') {sel = 1;} //если это определяющий символ, то переключаем селектор if (myChar == 'S') {sel = 2;} if ((myChar > 47) && (myChar < 58 )) {inputString += myChar;} //добавляем "байт" в строку } if (stringComplete) { //если строка закончена pserial.println(inputString); //отправляем её в порт для контроля if (sel == 1) {brnd = inputString.toInt();} //в зависимости от селектора присваиваем переменным значение if (sel == 2) {speed = inputString.toInt();} sel = 0; //выключаем селектор inputString = ""; // очищаем строку stringComplete = false; //убираем метку } }
Так вот, строка 10 работает не так, как в "штатном" примере SerialEvent.ino - не хочет собирать набор цифр в строку, а "перезаписывает" новыми, т.е. на выходе я получаю последнюю цифру. Например, отправляю "A321F", передаются все символы, а команда в строке 13 выводит только "1".
Ткните, пожалуйста, что не так.
Также через несколько отправок данных (штук 10 таких, как выше в примере) начинаются глюки, то строчит непонятные символы самопроизвольно, то просто теряет часть.
Полный код текущей программы ниже
#include <TVout.h> #include <font6x8.h> #include <font8x12.h> #include "Wire.h" #include "ford.h" #include "fuellvl.h" #include "l100km.h" #include "mlhour.h" #include "temp.h" #include "trip.h" #define DS1307_ADDRESS 0x68 #include <pollserial.h> pollserial pserial; TVout TV; unsigned long prev_ms=0; unsigned int aver_h=0; unsigned int aver_100=0; unsigned long brnd=0; unsigned int speed=0; unsigned long distance=0; unsigned int avg=0; int second; int minute; int hour; int weekDay; int monthDay; int month; int year; int ms1; int T=0; int F=0; int sel; String inputString = ""; boolean stringComplete = false; char myChar = 0; void setup() { TV.begin(_PAL,144,81); TV.select_font(font6x8); Wire.begin(); TV.set_hbi_hook(pserial.begin(57600)); inputString.reserve(20); } void loop() { if (pserial.available() > 0) { //если есть данные в буфере delay(3); myChar = (char)pserial.read(); //считываем байт pserial.print(myChar); //отправляем в порт для контроля if (myChar == 'F') { stringComplete = true;} //если пришло окончание строки, то ставим метку if (myChar == 'A') {sel = 1;} //если это определяющий символ, то переключаем селектор if (myChar == 'S') {sel = 2;} if ((myChar > 47) && (myChar < 58 )) {inputString += myChar;} //добавляем "байт" в строку } if (stringComplete) { //если строка закончена pserial.println(inputString); //отправляем её в порт для контроля if (sel == 1) {brnd = inputString.toInt();} //в зависимости от селектора присваиваем переменным значение if (sel == 2) {speed = inputString.toInt();} sel = 0; //выключаем селектор inputString = ""; // очищаем строку stringComplete = false; //убираем метку } } if ((millis() - prev_ms) >= 100) { //создает временные отрезки, чтобы распределить нагрузку prev_ms = millis(); ms1++; if (ms1 == 2) { Temp(); FuelLevel(); Speed(); } if (ms1 == 4) { getDate(); //получение даты и времени TV.print(76,2, " "); if (brnd > 99999) { TV.print(76,2, brnd);} else { if (brnd > 9999) {TV.print(82,2, brnd);} else { if (brnd > 999) {TV.print(88,2, brnd);} else { if (brnd > 99) {TV.print(94,2, brnd);} else { if (brnd > 9) {TV.print(100,2, brnd);} else { TV.print(106,2, brnd); } } } } } TV.print("ml"); } if (ms1 == 6) { printDate(); //вывод даты и времени } if (ms1==10) { ms1=0; } } } byte bcdToDec(byte val){ // Convert binary coded decimal to normal decimal numbers return ( (val/16*10) + (val%16) ); } void Temp() { T=analogRead(6); TV.bitmap(85,38,temp); if (T>830) {TV.print(104,43, "STOP");} else { if (T<=830 && T>610) {TV.print(104,43, "COLD");} else { if (T<=610 && T>500) {TV.print(104,43, "norm");} else { if (T<=500 && T>390) {TV.print(104,43, "NORM");} else { if (T<=390 && T>310) {TV.print(104,43, "WARM");} else {TV.print(104,43, "HOT!");} } } } } } void FuelLevel(){ //уровень топлива F=analogRead(7); if (F>=575) {F=0;} else if (F<575 && F>=553) {F=5;} else if (F<553 && F>=530) {F=10;} else if (F<530 && F>=508) {F=15;} else if (F<508 && F>=487) {F=20;} else if (F<487 && F>=465) {F=25;} else if (F<465 && F>=433) {F=30;} else if (F<433 && F>=401) {F=35;} else if (F<401 && F>=368) {F=40;} else if (F<368 && F>=324) {F=45;} else if (F<324 && F>=280) {F=50;} else if (F<280 && F>=235) {F=55;} else if (F<235) {F=60;} TV.bitmap(0,38,fuellvl); TV.print(22,38, F); TV.print(" "); } void getDate(){ Wire.beginTransmission(DS1307_ADDRESS); byte zero = 0x00; Wire.write(zero); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 7); second = bcdToDec(Wire.read()); minute = bcdToDec(Wire.read()); hour = bcdToDec(Wire.read() & 0b111111); //24 hour time weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday monthDay = bcdToDec(Wire.read()); month = bcdToDec(Wire.read()); year = bcdToDec(Wire.read()); } void printDate(){ if (monthDay < 10) {TV.print(81,57, "0"); TV.print(monthDay);} else {TV.print(81,57, monthDay);} TV.print("."); if (month < 10) {TV.print("0"); TV.print(month);} else {TV.print(month);} TV.print("."); TV.print(year); if (weekDay==0 || weekDay==7) {TV.print(81,65, "Su ");} if (weekDay==1) {TV.print(81,65, "Mo ");} if (weekDay==2) {TV.print(81,65, "Tu ");} if (weekDay==3) {TV.print(81,65, "We ");} if (weekDay==4) {TV.print(81,65, "Th ");} if (weekDay==5) {TV.print(81,65, "Fr ");} if (weekDay==6) {TV.print(81,65, "Sa ");} if (hour < 10) {TV.print(99,65,"0"); TV.print(hour);} else {TV.print(99,65, hour);} TV.print(":"); if (minute < 10) {TV.print("0"); TV.print(minute);} else {TV.print(minute);} } void Speed(){ TV.select_font(font8x12); //смена шрифта на большой и вывод скорости TV.print(55,22, "///"); if (speed > 99) {TV.print(55,22, speed);} else { if (speed > 9) {TV.print(59,22, speed);} else {TV.print(63,22, speed);} } TV.select_font(font6x8); TV.print(56,34, "km/h"); }
Не разобрался в вашей проблеме со строками, но...
Вы собираете байты в строку только для того что бы сделать toInt? Не практично, по моему. Я бы сделал так
10: if ((myChar > 47) && (myChar < 58 )) {inputInt = inputInt * 10 + myChar - '0';} // накапливаем число
17: inputInt = 0;
Честно говоря, тоже лень выковыривать "что же тут нет", но...
Если формат данных можно менять, то я бы, скажем ввел для простоты еще один символ. Скажем 'D' означающий "внимание, сейчас будет число" (если только выши 'A' и 'S' уже не являются подобным символом).
Тогда можно не морочить голову собиранием строк, а воспользоватся Arduino - ParseInt, который тем и знимается: собирает цифры в число, пока не встретится какой-нибудь не числовой символ (например символ конца строки).
Кстати - про конец строки. Почему 'F', почему не '\r' - перевод каретки или '\n' - символ конца строки. Достаточно выставить соотвествующий line ending (в сериал мониторе, чуть левее скорости) и тогда не нужно будет руками самому дописаться 'F' постоянно.
Если формат данных менять нельзя, то можно вспомнить про Arduino - Peek - посмотреть какой там символ пришел из Serial (но не забирая его из буффура), если myChar>='0' && myChar<='9', то вызываем Serial.parseInt(), если нет - ваша старая логика.
P.S. String - это зло. string - это феншуй.
Данные могу менять как угодно, пока всё не критично, это эксперимент :)
toc, смысл уловил, попробую так. Спасибо!
leshak, A, S и др. буквы перед числом (или вернее "набором цифр, которым нужно стать числом") определяют какой переменной потом нужно присвоить число.
Свой символ конца строки ввёл, т.к. начались глюки. В примере видел '\n'.
String взял в примере и думал, что как раз феншуй :) Попробую string.
Serial.parseInt() нашел не сразу, где-то позавчера. Еще не пробовал будет ли работать, я ж библиотеку pollserial использую.
Спасибо! Буду пробовать.
Я пытаюсь наладить связь с ПК, хотя подозреваю, что Мини Про через PL-2303 может подглючивать. Кстати, первые 2 переданных символа после включения неверно читаются: чтобы я не передавал, а на выходе знак табуляции и еще что-то (закономерность я не уловил, разные символы).
Вообще это будет связь двух микроконтроллеров (Mega2560 и Mini Pro) и всё это будет жить в авто. Бортовой комп. с дисплеем 1602 был сделан, работал, но потом мне попал в руки 4,3" монитор с двумя видеовходами: теперь отступать некуда :) ТВ-выход не может работать вместе с частыми прерываниями, но об этом я узнал тогда, когда в приборной панеле уже был врезан экран :) На этапе тестирования схалтурил...
Поэтому взят Mini pro и поэтому я достаю вас вопросами.
Днем попробую подключить Mega2560 к ПК через Serial, к меге через Serial1 - Mini Pro и передавать команды с ПК через "посредника", тем более в перспективе им вместе и работать.
>String взял в примере и думал, что как раз феншуй :) Попробую string.
Ну вы так "не заморачивайтесь". Это утверждение было именно из серии "священные войны". String - проще. Но это чисто "ардуино фишка". Просто я так предпочитаю. Один раз разобратся с обычными c-шными строками и жить спокойной жизнью (использовать стандартные с-шные либы для работы со строками и т.п.) . Вообщем string - порог входа выше, зато именно из-за этого (из-за понимания "что у них внутри") - жить легче.
Но, в вашем случае, я предлагал попробовать вообще уйти от необходимости "собирать строку". parseInt делает это внутри себя. Правда.... на этот момент он блокирует поток. Если каждая цифра поступает, скажем, с интервалом в 100ms, то число 123 будет останавливать скетч на 400ms (почти пол-секунды).
Вообщем я бы предложил (я это уже и сделал), попробовать вычитывать цифры "блокируя", а если это создаст проблемы - тогда уже разбиратся с посимвольным приемом и сбором строк.
>я ж библиотеку pollserial использую.
Если она наследуется от Stream (а "по феншуйному" именно так она и должна делать), то у нее тоже будет parseInt. Если нет... то вообщему-то не сложно написать самому просто отдельной функцией в скетче.
>A, S и др. буквы перед числом (или вернее "набором цифр, которым нужно стать числом") определяют какой переменной потом нужно присвоить число.
Можно не "потом", можно попрбовать сразу.
Или вот, к примеру кусочек кода из моего проекта. У мне есть фунция setOneOutput(channelNo,newLevel) которая выставляет уровень яркости на канале. Исть функция allOff() которая выключает все каналы, и есть фунция allOn(newLevel) которая выставляет уровень сразу всем каналам. Теперь я хочу рулить ими коммандами из Serial.
Команды у меня таки:
"f" - выключить все. то есть нужно вызвать allOff();
"n123" - включить все на уровне 123, то есть вызвать allOn(123)
"l3,255" - включить 3-тий канал, на уровень 255. То есть вызвать setOneOutput(3,255);
В коде это будет выглядит так:
>набором цифр, которым нужно стать числом
Эх... знали бы вы, как трудно до многих доходит это :(. Что чило состоит из цифр. А когда выясняется, что из serial у нас приходит не цифра, а код символа цифры - вообще мозговой ступор начинается :)
>ообще это будет связь двух микроконтроллеров (Mega2560 и Mini Pro)
Значит вам нужно ставить Line Ending в вариант "Both" и учится обрабатывать именно этот случай. Так как именно он идентичен тому, как отправляет данные Serial.println() (заканчивает строки на \r\n)
>но потом мне попал в руки 4,3" монитор с двумя видеовходами:
Та же история... повесил камеру заднего вида, к ней пришлось повесить зеркало с монитором встроенным, а у него два видеовхода.... один не используется, а это "муляет" :)
Только я, если займусь этим, наверное в любом случае все-таки буду пытаться заставить работать аппаратный Serial.
>2 переданных символа после включения неверно читаются: чтобы я не передавал, а на выходе знак табуляции и еще что-то (закономерность я не уловил, разные символы).
Можно попробовать сделать подтяжку RX-са. А можно просто не морочится.. и сделать что-то типа:
После включение тупо очистить входной буффер. Ну и на передающей плате, сделать небольшую задержку после включения. Что-бы ее данные не приняли за мусор. Это, естетсвенно в предположении что они обе включаются одновременно.
А можно и вообще забить на это... код выше читает "нужные ему комманды", а все что "не нужно" - тупо игнорит. Так что если пробежит пару мусорных байтов - то и фиг с ним. Главное что-бы они не сложились в осмысленную комманду :)
Кстати, возможно пригодится ссылочка
"TVout Color - NTSC" - http://forum.arduino.cc/index.php?topic=169674.0
В отличие от TVOut может может выдавать цветной NTSC
Arduino TVoutColor NTSC - YouTube
Arduino TvoutColor NTSC Trial2 - YouTube
Через мегу еще не подключился, пока переделал код на простой сбор числа, как написал toc, глюки продолжаются, хотя то, как работает когда не глючит - мне нравится :) Также убрал необходимость отправлять завершающий символ "F", реагирует на символ окончания строки, который буду передавать командой serial.println();
Сделал скрин. Примерно от 10 до 20 отправок данных через монитор порта и всё - Mini Pro виснет, а перед этим, начинает какую-то ахинею принимать и возвращать (скорость выставлена правильно и переход на 9600 ничего по-сути не меняет):
Сейчас возьмусь за переделку кода Mega2560 (борт. комп), чтобы завтра проверить связь без "переходника для прошивки".
Кстати, возможно пригодится ссылочка
"TVout Color - NTSC" - http://forum.arduino.cc/index.php?topic=169674.0
В отличие от TVOut может может выдавать цветной NTSC
Arduino TVoutColor NTSC - YouTube
Arduino TvoutColor NTSC Trial2 - YouTube
Мне на том же форуме дали ссылук на несколько проектов: http://www.hackster.io/janost
Но всё это не для моего уровня :) Надо еще неплохо так "подкачаться" :)
melvladimir, от всех String'ов избавились? Когда глючит, одна из возможных причин - дефицит оперативной памяти.
Или где-то выход за границы массивов. Или где-то сделали случайно print, какому-нибудь char* в том или ином виде. И не побеспокоилсь о 0-терминаторе.
Вообщем не видя код - не о чем говорить. Но... по описанию траблы, больше похоже именно на софтофую, а не железную.
String убрал, массивы не использую, разве что RTC DS1307 где-то "чудит".
Весь код с комментариями (если не передавать данные, то работает хоть весь день):
Похоже не хватает оперативной памяти. Дописал код до полного функционала - вообще не работает.
Начал срезать по кускам - заработал. Причем куски по-отдельности - работают.
Сейчас буду переписывать и оставлять минимум глобальных переменных. Попробую построить программу на 2-3 переменных.
Хотя странно... у AtMega328p 1кБ ОЗУ - должно же хватать.
Ну, для начала погуглите как измерять "сколько сейчас памяти есть".
Во вторых, всякие строки в PROGMEM упихивать. Правда у вас тут длинных строк особо не видно, а перенос строк в пару символов особого выигрыша не дает, но.... похожими "пожирателями", могут выступить ширфты и "значек, значек, логотип...". Можно попытся их в PROGMEM , если они еще не там.
Попытатся заставить, все-таки, работатьь програмный Serial. Софтварный, он же тоже память кушать хочет...
Ну и оптимизации. Искать повторяющиеся куски, выделять их в функции. Или вещи типа:
свернуть как-то так:
и т.д. и т.п.
Про ОЗУ читал, но тогда не разобрался :) Надо видимо вникать. Сейчас поставлю IDE 1.5.6 r2 - посмотрю сколько памяти под переменные отводится. Ну и надо будет вникнуть в определение свободной ОЗУ.
Попробую для начала часть глобальных переменных сделать локальными.
+ есть мысль использовать вместо 10 переменных - 2: одну - для хранения числа, а вторую - для определения куда это число "рисовать". У меня ведь на экран графика выводится. Попробую не ряд мелких значков, а один крупный и перерисовывать его раз в несколько секунд, а данные выводить "поверх".
Sketch uses 13 832 bytes (45%) of program storage space. Maximum is 30 720 bytes.
Global variables use 484 bytes (23%) of dynamic memory, leaving 1 564 bytes for local variables. Maximum is 2 048 bytes.
Говорю ж - должно хватать ОЗУ :) ерунда какая-то... буду ковыряться дальше
Буквально вчерась отписывал в соседней ветке, что эти цифры по памяти - никакакого значения не имеют. Они могут подсказать только если есть явная и грубая попытка превысить. Скажем объявить массив размером мегабайта на два.
Узнать же, на этапе компиляции РЕАЛЬНЫЙ расход памяти - теоретически не возможно. Так что если тут говорит "занято не много" - это ничего не значит. Скажем вызвала какая-то библиотека, malloc(someVars); Глядя на этот вызов вы можете сказать сколько памяти израсходовалось? Нет. Потому что не знаете значение someVars на момент вызова. И компилятор - тоже не знает.
К сожалению, насколько я знаю ТОЧНО узнать расход памяти можно только с помощью JTAG дебагера :( Ну или в эмуляторе (PROTEUS и т.п.) пытатся запустить.
Примерный расход, можно узнать програмно. Вот тут ест несколько способов из серии "черная магия":
Arduino Playground - AvailableMemory
В свое время перебирал их. Не помню какой, но только один мне начал выдавать что-то "правдоподбное" (объявляю пару строк - расход памяти увеличивается, убираю пару символов" - уменшается).
Как раз это читаю сейчас.
Также бегло посмотрел pollserial - вроде как измененный аналог serial, т.е. аппаратный, а не программный.
Просто в программе и расчетов особо нет: взял переменную - показал. Насколько ждрет память "показал" - не известно. Но в то же время отображение и обновление значков - работает без глюков хоть весь день. Проблемы начинаются при попытке приема и обработки. Что наталкивает на мысль о "софтварности" serial. Копаю дальше.
Хотя странно... у AtMega328p 1кБ ОЗУ - должно же хватать.
Похоже AtMega328 с вами не совсем согласна :(
Давайте посмотрим сколько же памяти нужно для одного пикселя этой библиотеке:
Смотрим https://code.google.com/p/arduino-tvout/source/browse/TVout/TVout.cpp
То есть, на один пиксель нужен один байт.
Смотрим как вы вызываете эту функцию (какое у вас разрешение):
144*81=11664byte
То есть ~11.3кБ только на видеопамять у вас ушло.
Чисто из любопыства, пустите, что-то типа
Что-нибудь выводит?
Про 1байт/пиксель не совсем понял. В коде не рылся, т.к. бесполезно, вряд ли пойму, но когда рисовал шрифты и картинки, то 1 пиксель=1бит, т.е. строка типа 0b0001110 "включит" 3 пикселя. Или, например, код цифры 7:
Код минут через 30 попробую, правда не понял как он работает... Инициализация ТВ-выхода есть, но при этом код на экран ничего не "отрисовывает".
Зачем рыться в коде? Ну например что-бы лучше понимать что происходит. Примеры же вы смотрите? Чем код библиотеки отличается от примеров? Тем более даже если там "зубодробительный код", то даже среди него можно найти понятные строки. Коментарии там почитать и т.п. Например описание что возвращает фунция TVOut.begin
В дан-ном же случае даже рыться не нужно. Я уже порылся за вас и привел вам сюда исходит функции. И даже выделил жирным строку на которую нужно обратить внимание. Если непонятно что она делает, то осталось только загуглить что такое malloc() и прочитать ее описание. А потом прикинуть какое число ей передатся когда мы вызовем ее с x,y - 144,81
>Про 1байт/пиксель не совсем понял.
В каком виде вы картинки кодируете - в данном случае рояля не играет. Важно то, в каком виде внутри себя, библиотека хранит данные о том что сейчас нарисованно на экране. А внутрях она для каждого пикселя выделяет байт. Почему целый байт - я не знаю. Может быть просто "лень было", может для скорости, (выделяем байт, а используем только бит), может для того что-бы в градациях серого рисовать (скорее всего), может задел на будущую многоцветность.
Вообщем картинки у вас - действительно "однобитные". Черно-белые. А вот "видео-память" - "байт на пиксель".
>но при этом код на экран ничего не "отрисовывает".
А этот код ничего и не должен отрисовыать. В Serial Monitor смотрите. Есть там надпись типа "TV init error=4"?
Есть "TV init error=4". Сразу после старта.
Возможно многоцветность или оттенки серого планировались, но так и не были реализованы.
Вчера-сегодня переписывал код. Убрал по максимуму перепенные. Также попробую снизить разрешение до 128х72 точки.
ЗЫ: всё равно не понимю почему сдыхает при передаче инфы. Ведь: "pollserial.h Heavily modified version of:
HardwareSerial.h - Hardware serial library for Wiring". Пока не передаешь - работает, читает 2 аналоговых порта, отображает время, всё это красиво рисует...
По-моему я нашел ось зла: часики...
Загрузил переписанный код, где минимальное кол-во переменных, IDE написало справочную инфу о том, что 462 байта ОЗУ заняты (было 484). Вгрузил - не фурычит. Кое-что несущественное переписал - тоже не работае. Тут решил наугад выбрасывать блоки и начал с отображения даты/времени (включая библиотеку) и эврика:
Sketch uses 11 268 bytes (36%) of program storage space. Maximum is 30 720 bytes.
Global variables use 212 bytes (10%) of dynamic memory, leaving 1 836 bytes for local variables. Maximum is 2 048 bytes.
Сейчас играюсь передачей данных, штук 100 разных строк отправил - работает. Вплоть до "4294967295" отправлял - нормально работает.
Конечно, надо чуть-чуть поправить, а так - всё ОК. Сейчас еще хочу попробовать измерить кол-во свободной памяти.
Значит изначально я неправильно поставил вопрос (обозначил виновника), видимо конфликт троицы TVout+Wire+Serial.
Ах, да, код сейчас выглядит так (используется одна переменная для приема символов, другая для сбора из символов числа и третья - для определения в какое место экрана выводить собранное число):
Сейчас попробую измерить свободную ОЗУ и буду переходить к тестированию работы двух МК в связке. И потом надо будет решать вопрос с датой и временем...
По ссылке http://playground.arduino.cc/Code/AvailableMemory взял первый и последний способы (библиотека + кусок кода и просто код).
Sketch uses 12 008 bytes (39%) of program storage space. Maximum is 30 720 bytes.
Global variables use 238 bytes (11%) of dynamic memory, leaving 1 810 bytes for local variables. Maximum is 2 048 bytes.
В монитор порта приходит раз в 2 минуты (вызов по таймеру на базе millis(), перед этим идет чтение двух аналоговых портов и отрисовка двух значков со значениями на экране):
freeMemory()=267
freeRAM()=273
freeMemory()=267
freeRAM()=273
Перед первым замером - передал все необходимые параметры. Ну оно ни на что не повлияло.
Таким образом возможно причина не в конфликте библиотек, а таки в нехватке памяти, но и конфликт исключать не стоит.
Есть "TV init error=4". Сразу после старта.
Печалька. Теперь смотрим в файлик https://code.google.com/p/arduino-tvout/source/browse/TVout/TVout.cpp
И читаем что означает код возврат из TvOut.begin
Правда, если посмотреть в код, ошибки (1) и (2) там никогда вернутся не могут. А вот return 4 - имеется.
И возвращается именно когда не удалось выделить память под видео-буффер. В резульатте этого буффер (поле screen) - имеет значение null. render_setup() - не выполнился.
Далее, фактически, все попытки что-то рисовать/писать пишут/меняют не выделенный указатель. Куда-то "в начало памяти". Что там окажется по этим адресам, что перезапишется/перетрется или поменяется другими библиотеками - никто не знает. Чисто как повезет. Могут чужие данные там оказатся, может код самого скетча....
Поэтому подбирать кто там виноват в троице "TVout+Wire+Serial" - не имеет смысла. Виновник известен - TVOut которому не хватило памяти, мы это не проверили, но заставили работать. Врезультате он работает в режиме "на кого попало". И ловить можно совершенно разные и мистические глюки. И долго перебирать комбинации "что-бы работало". Но даже если "заработло", то это совершенно не означет что будет работать. От чиха все рухнет. Скажем первая цифра текущего времени 3 - может работать, и 8 - мь все осыпится....
Вообщем этом как в машине. Вода в масле. Амальгама. Вроде завелся, но когда поймает клин - никому не ведомо.
При этом лампочка что давления масла нет - горит (код ошибки 4-ре).
Таким образом возможно причина не в конфликте библиотек, а таки в нехватке памяти, но и конфликт исключать не стоит.
Не возможно, а "так и есть". А причина конфликта - нехватка памяти.
Почему у вас это вызывает сомнение, непонятно. Сообщении 17-ть я вам привел код функции begin, которую вы вызваете. Посмотрите на него. Ничего сверх-сложного в нем нет. Поведение - очевидно. И предсказуемо если взять калькулятор и умножить 144 на 81.
Вообщем если только вы не используете какую-то другую версию библиотеки, не ту что по ссылке которую я давал, то на 328 камне с данным разрешением корректно и гарантированно стабильно эта библиотека без переделок - не будет.
Есть вероятность, что я ошибаюсь, но..... возвращенный код 4 говорит об обратном. Может быть это остатки какого старого кода, который уже не используется..., но другого, который работает не через этот буффер screen - я не вижу в коде.
Да и само наличие "глюков не объяснимых" говорит что, все-таки, к сожалению, я прав.
Спасибо за помощь и детальное разъяснение!
Контрольная проверка свободной памяти практически это же показало.
Сейчас буду думать над вариантами и тестировать...
В конце-концов, могу попробовать поменять местами Mega2560 и Mini Pro, да и еще не пробовал снизить разрешение. А время могу передавать также, как и другие переменные - через serial.
Еще раз спасибо! А то задолбался уже :) знаний не хватает, но очень хочется...
К сожалению на ~11.3кБ видеобуфера, памяти не хватит даже у меги 2560-той. У нее SRAM - 8 KB.
Так что тут либо смотреть в сторону более взрослых камней. Скажем DUE с ее 96 KBytes of SRAM, либо снижать разрешение, либо перепахивать библиотеку, выкидывать цвет, делать хранение действительн "бит на пиксель".
Либо, подключать внешнюю память. Аппаратная поддержка внешней памяти (когда ее реально становится "просто больше"), насколько я знаю есть только у мег. Но.. честно говоря знаком с этим только теоретически.
512Kb SRAM expansion for the Arduino Mega (design) | Andys Workshop
Upgrading RAM in an Arduino Mega
Можно и к 328 добавить память.
Using SIMMs to Add Some Extra RAM on your Arduino UNO
Но общатся с ней прийдется чере SPI/I2C. Что означает, опя-таки, необходимость переделки библиотеки. И это все в предположении, что SPI/I2C шине хватит скорости.
Одно бесспорно радует: 3 часа работает Mini Pro, периодически кидаю ему данные для отображения и принимаю инфу о свободной памяти. Всё ОК. При этом не стесняюсь кормить его на всю емкость переменной unsigned long (без фанатизма, т.к., например, под скорость отведено 3 знака, ну можно 6 втулить, но больше - перекосит картинку). Также периодически чищу экран путем вывода "зашитых" сообщений, перед которыми выполняется очистка экрана.
Переделать библиотеку или подключить внешнюю память - вряд ли смогу. Слишком мало знаний и опыта. Проведу ряд "боевых" тестов, а там - видно будет.
Ну, как я уже говроил, это "работает" - чистно на везении. Когда и от чего заглючит - нередсказуемо.
Кстати, если будете уменьшать разрешение, то не забудте, что "Horizonal resolution must be divisable by 8."
Хоть в begin и нет проверки на это (но явно планировалось), дальше по коду много где это предполагается. Кратность 8-ми.
И в коде таки видно, что по крайней мере планировась (возможно уже и доделано), что разрешение может быть меньше чем PAL/SECAM. Видны переменные для маштабирования. По крайней мере по y-ку увидел.
Возможно там и по x-су есть, но там уже ассемблерные вставки :(. А я с ассемблером, последний раз общался в начале 90-тых. И то... парочка программ на 20-30 строк.
Разрешение я испробовал одним из первых :) так сказать - методом тыка (но в пропорциях и с кратностью 8).
Сейчас читаю библиотеку, пытаюсь понять, что в ней происходит :)
Прочитал по функции выделения памяти malloc, не понятно зачем так сделано... ведь библиотека писалась под "Arduino" (т.е. разные МК), а среди всего набора мало какой МК может похвастаться обилием памяти. Mega2560 едва подходит под уменьшенное разрешение 96*72 (вот не помню, работало оно у меня или нет, точно работало 128х72). А поддержку Mega2560 добавили позже выхода библиотеки.
Также вселяет надежду и остаток свободной памяти - 273Б, что может говорить о том, что "рисунок экрана" таки бит/пиксель (хочется все же надеятся). Тогда занято: 2048 - 273 = 1775Б
144*81 / 8 = 1458Б + 238Б глобальные переменные (то, что написал компилятор) = 1696Б
1775 - 1696 = 79Б ушло на всякие операции.
Ну оптимистично же? :)
Можно этот же код загрузить в Mega2560 и если логика верная, то должно быть свободно ~6417Б памяти. Щаз это и проверю :)
ЗЫ: 5 часов подряд - всё ОК.
Сказано - сделано :) Тот же код залит в Mega2560:
Sketch uses 12 096 bytes (4%) of program storage space. Maximum is 258 048 bytes.
Global variables use 238 bytes (2%) of dynamic memory, leaving 7 954 bytes for local variables. Maximum is 8 192 bytes.
А в монитор порта пришли заветные цифры:
freeMemory()=6408
freeRAM()=6415
Что соответствует оптимистичному расчету выше :) (расхождени на 2Б спишем на погрешность работы измерялок и/или разность в МК, всё таки библиотеки используются, а не полностью правильный код).
Всё, можно теперь спокойно отдохнуть :)
>Также вселяет надежду и остаток свободной памяти - 273Б,
Не на отчеты freeMemory() смотреть нужно, а на то что вам вернула TVOut.begin(). Пока она не вернет ноль - ни о какой стабильности речи быть не может. Если вернула ноль - значит она смогла выделить память под запрошенное разрешение. Хватило. И эта память уже будет "занята ей". Другие библиотеки в нее не полезут читать/писать. И она записывая туда - никому не повредит.
А пока она возращает 4-ре, значит память выделить не удалось. Вы радостно смотрите на freeRam(), которая показывает что память не занята... Конечно не занята раз зарезирвировать ее для нужд TVOut не вышло.
Больше склоняюсь к ошибке в библиотеке. Т.к. 1 байт на пиксель - это много для ч/б. Это уже 256 оттенков серого или 256 цветов.
У какого МК из этого перечня: "m168, m328, m1280, m2560, m644, m1284p" есть 128*96=12228Б + переменные = 16кБ ОЗУ? Ни у какого. А все они работают с ТВ-выходом на "стандартном" разрешении.
Для чего в библиотеке та драконовская функция - не ясно. Возможно для рисования "динамической" графики типа "тетриса", появление и исчезания геометрических фигур и др.
#$@#$@#$#$!!!!!!!!!!!!!!!!!!!!!!!!!
Так да... бит на пиксель.
Всего-то на строчку выше глянуть нужно было
То есть, не 144*81=11664byte нужно, а (144/8)*81=1458 байт. Что, в случае с мегой - уже выглядит вполне реально. И с 328 - тоже реально, если только уже в своем скетче скромно вести себя по поводу памяти.
Сдругой стороны, не полезли бы смотреть в код, не увидили бы что есть код возврата 4 означающий нехватку памяти. А он у нас таки был.
Так что добиватся того что-бы TVOut.begin возвращал ноль - все равно нужно. Но теперь это выглядит более/менее реальной целью ;)
так когда ждать
для
20$ ???
а то у меня тут не влезает
мне пожалйсто в SEKAM кодировке со звуком DolbyDigital5.1 вполне устроит
еще не плохо чтоб по web-интерфейсу управлялся ну и XBMC работал
неплохо H.264 раскодировочку добавить хотябы с MPEG2
ну и кардшаринг от моего легального dreambox7000
и еще неплохобы азимут угламеста потому как на тарелках моторы уже есть
преспрашиаю для непонятливых
8 бит и меньше мозга чем у Sinclair ZX Spectrum 64kbye CGA с магнитофоном с постоянной подкачкой кода. ~80$+80рублей
если мутно дебило графики вы еще сможете получить
то такой уровень графики CGA без матсопрцессоров вам даже не светит
TV и Arduino - это вы наверно сьели что-то?
то что на гитнабе код лежит это не значит что он нормальный писал
видел я сайт где собрано 10 попроще игр от sinlair чернобелых
авот бьет себя пяткой в грудь что ардуинка проталкивает их
вполне может быть
ну только ради спортивного интереса
ну нифига себе запустилась
и фиг с ним что на синклере в разы она веселей с музлом попикиваением
Глупость человеческая безпредельна.
Разум человеческий имеет предел.
в голову не приходило
а чего-то люди не синклер повторяют в одном корпусе
а головы ломают как хотябы в несколько каких-то камушков засунуть хоть что-то
приличное для графики ~100$
каке
ие
я ионогда смотрю как спец заточенная за ~100$ ворочает графику
и думаю а не тормоз ли он
про 35$ за raspberry это вы идиотам можете рассказывать
я личто собрал и уменя ценник без телевизора клавы мыши флешки пачкордов 190$ !!! за что-то приличное для графики
а вы на 20$ хотите видеопоток не гнусный хуже CGA 320x200 имея всего 30 килобайт для кода
ну-ну
Когда дойдете до уровня 1980-ых годов и увидите что в конце концов получается полное авно в 2014-ом
Я даже знаю ваш дальнейший шаг
Вы будете разрабатывать математический сопроцессор для графики в виде чудо-шилда
и будете втыкать его в arduino uno за 150$
народ на ЧПУ станках с таким трудом достигает 30кГц реальных команд от 20$+3*5$
а тут 4 мегагерца хотят на выходе типа и почемуй-то у меня массивчик не влезает давайте битики подсчитывать
А зачем ему туда влезать?
ну вот отбил желание ковыряться в 20$
Всю простыню не осилил :)
К чему сей "опус"? Желаемый результат был достигнут и меня всё устраивает. Еще немножко дописать и будет всё "в ёлочку".
...результат был достигнут ...
поподробней можно?
Результат - это вывод нужных данных на экран, без зависания, задержек, мерцания.
Есть бортовой комп. в автомобиле. Есть 4,3" экран с двумя тв-входами. "ТВ-выход" не любит частые и множественные прерывания, к тому же влияет на работу millis(). Взял Mini Pro для вывода данных с борт. компа на экран. Несколько дней мучился переписывая так и сяк код, потом создал эту тему, пришли гуру и натыкали носом в ошибки и помогли вникнуть в работу библиотеки. Ряд ошибок устранил и уже Mini Pro нормально принимает данные и отображает на экране. Надо еще чуть полирнуть и будет так, как задумывалось и даже круче :)
melvladimir, фотку покажите?
Фотка с телека, в машину МК пока не ставил, надо еще дописать вывод нескольких параметров + хочу меню сделать.

А в приборке экран выглядит так (это старая фотка, как видно по дате, первое тестирование):
понятно
хоть терминал
Чуть переделал прием данных: теперь есть числовые и строковые данные, хотя и то и другое передается символами, а не байтами. С байтами не дружу, хотя может байтами таки проще и/или эффективнее.
Так дробные и/или отрицательные числа идут в виде набора символов, собираются в строку и строка выводится на экран. Немного щаз подзавис с передачей даты/времени... хотел сделать передачу только тех данных, которые изменились, а потом вспомнил, что у меня бывает условие очистки экрана и вывода текста и если возобновить работу МК, то на экран будет отрисовываться минуты, а остальное - надо долго ждать :) Надо чуть переписать :)
На данный момент протестирована работа нижеследующего кода (может кому пригодится). По-сути Mini Pro работает как "контроллер экрана" с единственной задачей - вывод данных на экран и всё.
А выглядит на экране это так:
Еще не подключил датчики температуры и RTC модуль, но остальные данные передаются и отображаются четко.
Ну и еще надо доделать вывод меню и др., но на работу не повлияет.
Привет, не понятно как ты получаешь данные с авто, я так понимаю без OBD? У меня не получается одновременная работа на ардуине TVOut и ELM327-блютуз.
Еще не подключил датчики температуры и RTC модуль, но остальные данные передаются и отображаются четко.
Ну и еще надо доделать вывод меню и др., но на работу не повлияет.
Привет, не понятно как ты получаешь данные с авто, я так понимаю без OBD? У меня не получается одновременная работа на ардуине TVOut и ELM327-блютуз.
Привет!
Исходниками не поделитесь?
Не думали доработать проект под возможность использования в режиме Osd, то есть выводить данные поверх видеосигнала с камеры заднего вида?
Я считаю незачем данные выводить поверх видео с КЗВ.
Кому как, такой вариант думаю заинтересовал бы квадрокоптеров. Хозяин то пропал? Ds6328 может у тебя есть исходники?
У меня нет таких данных, я щас делаю отображение данных по блютузу от ELM327 на ардуину с монитором.
Получается? Ознакомиться с результатами можно?