Передача данных по UART при активном TVout

melvladimir
Offline
Зарегистрирован: 08.03.2013

Который день бьюсь над проблемой передачи данных от одного МК другому. Вернее на данный момент застрял на передаче данных через "монитор порта" к 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");
}

 

toc
Offline
Зарегистрирован: 09.02.2013

Не разобрался в вашей проблеме со строками, но...

Вы собираете байты в строку только для того что бы сделать toInt? Не практично, по моему. Я бы сделал так
10: if ((myChar > 47) && (myChar < 58 )) {inputInt = inputInt * 10 + myChar - '0';} // накапливаем число
17: inputInt = 0;

leshak
Offline
Зарегистрирован: 29.09.2011

Честно говоря, тоже лень выковыривать "что же тут нет", но...

Если формат данных можно менять, то я бы, скажем ввел для простоты еще один символ. Скажем 'D' означающий "внимание, сейчас будет число" (если только выши 'A' и 'S' уже не являются подобным символом).

Тогда можно не морочить голову собиранием строк, а воспользоватся Arduino - ParseInt, который тем и знимается: собирает цифры в число, пока не встретится какой-нибудь не числовой символ (например символ конца строки).

Кстати - про конец строки. Почему 'F', почему не '\r' - перевод каретки  или '\n' - символ конца строки. Достаточно выставить соотвествующий line ending (в сериал мониторе, чуть левее скорости) и тогда не нужно будет руками самому дописаться 'F' постоянно.

Если формат данных менять нельзя, то можно вспомнить про Arduino - Peek - посмотреть какой там символ пришел из Serial (но не забирая его из буффура), если myChar>='0' &&  myChar<='9', то вызываем Serial.parseInt(), если нет - ваша старая логика.

 

 

P.S. String - это зло. string - это феншуй.

 

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Данные могу менять как угодно, пока всё не критично, это эксперимент :)
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 и передавать команды с ПК через "посредника", тем более в перспективе им вместе и работать.

leshak
Offline
Зарегистрирован: 29.09.2011

>String взял в примере и думал, что как раз феншуй :) Попробую string.

Ну вы так "не заморачивайтесь". Это утверждение было именно из серии "священные войны". String - проще. Но это чисто "ардуино фишка". Просто я так предпочитаю. Один раз разобратся с обычными c-шными строками и жить спокойной жизнью (использовать стандартные с-шные либы для работы со строками и т.п.) . Вообщем string - порог входа выше, зато именно из-за этого (из-за понимания "что у них внутри") - жить легче.

Но, в вашем случае, я предлагал попробовать вообще уйти от необходимости "собирать строку". parseInt делает это внутри себя. Правда.... на этот момент он блокирует поток. Если каждая цифра поступает, скажем, с интервалом в 100ms, то число 123 будет останавливать скетч на 400ms (почти пол-секунды).

Вообщем я бы предложил (я это уже и сделал), попробовать вычитывать цифры "блокируя", а если это создаст проблемы - тогда уже разбиратся с посимвольным приемом и сбором строк.

>я ж библиотеку pollserial использую.

Если она наследуется от Stream (а "по феншуйному" именно так она и должна делать), то у нее тоже будет parseInt. Если нет... то вообщему-то не сложно написать самому просто отдельной функцией в скетче.

>A, S и др. буквы перед числом (или вернее "набором цифр, которым нужно стать числом") определяют какой переменной потом нужно присвоить число.

Можно не "потом", можно попрбовать сразу.


.....
byte ch=Serail.read()
switch(ch)
   case 'A':
                 aaa=Serial.parseInt();
                 break;
    case 'S':
                 sss=Serial.parseInt();
                break;
     default:
               break;
}

 

Или вот, к примеру кусочек кода из моего проекта. У мне есть фунция setOneOutput(channelNo,newLevel) которая выставляет уровень яркости на канале. Исть функция allOff() которая выключает все каналы, и есть фунция allOn(newLevel) которая выставляет уровень сразу всем каналам. Теперь я хочу рулить ими коммандами из Serial.

Команды у меня таки:

"f" - выключить все. то есть нужно вызвать allOff();
"n123" - включить все на уровне 123, то есть вызвать allOn(123)
"l3,255" - включить 3-тий канал, на уровень 255. То есть вызвать setOneOutput(3,255);

В коде это будет выглядит так:

  if(Serial.available()){
    byte ch=Serial.read();
    switch(ch){
      case '\r':
      case '\n':
                 break;
      
      case 'l':
          setOneOutput(Serial.parseInt(),Serial.parseInt());
          break;
       case 'f':
          allOff();
          break;
       case 'n':
          allOn(Serial.parseInt());
          break;

       default:
            Serial.println("unknown command");
            break;
    }
    
    while(Serial.available())Serial.read();
  }

 

 

 

>набором цифр, которым нужно стать числом

Эх... знали бы вы, как трудно до многих доходит это :(. Что чило состоит из цифр. А когда выясняется, что из serial у нас приходит не цифра, а код символа цифры - вообще мозговой ступор начинается :)

>ообще это будет связь двух микроконтроллеров (Mega2560 и Mini Pro) 

Значит вам нужно ставить Line Ending в вариант "Both" и учится обрабатывать именно этот случай. Так как именно он идентичен тому, как отправляет данные Serial.println() (заканчивает строки на \r\n)

>но потом мне попал в руки 4,3" монитор с двумя видеовходами: 

Та же история... повесил камеру заднего вида, к ней пришлось повесить зеркало с монитором встроенным, а у него два видеовхода.... один не используется, а это "муляет" :)

Только я, если займусь этим, наверное в любом случае все-таки буду пытаться заставить работать аппаратный Serial.

>2 переданных символа после включения неверно читаются: чтобы я не передавал, а на выходе знак табуляции и еще что-то (закономерность я не уловил, разные символы).

Можно попробовать сделать подтяжку RX-са. А можно просто не морочится.. и сделать что-то типа:

Serial.begin(57600);
while(Serial.available()); Serial.read();

После включение тупо очистить входной буффер. Ну и на передающей плате, сделать небольшую задержку после включения. Что-бы ее данные не приняли за мусор. Это, естетсвенно в предположении что они обе включаются одновременно.

А можно и вообще забить на это... код выше читает "нужные ему комманды", а все что "не нужно" - тупо игнорит. Так что если пробежит пару мусорных байтов - то и фиг с ним. Главное что-бы они не сложились в осмысленную комманду :)

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

Кстати, возможно пригодится ссылочка

"TVout Color - NTSC" - http://forum.arduino.cc/index.php?topic=169674.0  

В отличие от TVOut может может выдавать цветной NTSC

 

Arduino TVoutColor NTSC - YouTube

Arduino TvoutColor NTSC Trial2 - YouTube

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Через мегу еще не подключился, пока переделал код на простой сбор числа, как написал toc, глюки продолжаются, хотя то, как работает когда не глючит - мне нравится :) Также убрал необходимость отправлять завершающий символ "F", реагирует на символ окончания строки, который буду передавать командой serial.println();

Сделал скрин. Примерно от 10 до 20 отправок данных через монитор порта и всё - Mini Pro виснет, а перед этим, начинает какую-то ахинею принимать и возвращать (скорость выставлена правильно и переход на 9600 ничего по-сути не меняет):

Сейчас возьмусь за переделку кода Mega2560 (борт. комп), чтобы завтра проверить связь без "переходника для прошивки".

melvladimir
Offline
Зарегистрирован: 08.03.2013

leshak пишет:

Кстати, возможно пригодится ссылочка
"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
Но всё это не для моего уровня :) Надо еще неплохо так "подкачаться" :)

toc
Offline
Зарегистрирован: 09.02.2013

melvladimir, от всех String'ов избавились? Когда глючит, одна из возможных причин - дефицит оперативной памяти.

leshak
Offline
Зарегистрирован: 29.09.2011

toc пишет:
melvladimir, от всех String'ов избавились? Когда глючит, одна из возможных причин - дефицит оперативной памяти.

Или где-то выход за границы массивов. Или где-то сделали случайно print, какому-нибудь char* в том или ином виде. И не побеспокоилсь о 0-терминаторе.

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

String убрал, массивы не использую, разве что RTC DS1307 где-то "чудит".

Весь код с комментариями (если не передавать данные, то работает хоть весь день):

#include <TVout.h> //библиотека TVout
#include <font6x8.h> //основной шрифт для ТВ
#include <font8x12.h> //увеличенный шрифт для спидометра, только цифры
#include "Wire.h" //библиотека для работы RTC
#include "ford.h" //большой логотип-заставка, пока не используется
#include "fuellvl.h" //значок уровня топлива
#include "l100km.h" //значок мл/100км
#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; //мгновенный расход мл/100км
unsigned long brnd=0; //израсходовано топлива в мл
unsigned int speed=0; //скорость км/ч
unsigned long distance=0; //путь в метрах
unsigned int avg=0; //средний расход на 100км
int second; //секунды, нигде не выводятся
int minute; //минуты
int hour; //часы
int weekDay; //день недели
int monthDay; //число месяца
int month; //месяц
int year; //год
int ms1; //для отрезков времени
int T=0; //температура
int F=0; //уровень топлива
int sel; //определитель переменной, которой присваивается переданное значение
boolean stringComplete = false; //метка окончания передачи
char myChar = 0; //для принятия символа из буфера
unsigned long inputInt = 0; //для собирания числа из цифр

void setup()
{
TV.begin(_PAL,144,81); //формат и разрешение
TV.select_font(font6x8); //выбор основного шрифта
Wire.begin(); 
TV.set_hbi_hook(pserial.begin(57600)); //толком не знаю что это, взято из примера на сайте библиотеки TVout, отвечает за связь
}

void loop() {
	if (pserial.available()) { //если есть данные в буфере
		delay(3);
		myChar = (char)pserial.read(); //считываем байт
		pserial.print(myChar); //отправляем в порт для контроля
		if (myChar == '\n') {stringComplete = true;} //если пришло окончание строки, то ставим метку
		if (myChar == 'A') {sel = 1;} //определяем какой переменной присваивать
		if (myChar == 'S') {sel = 2;}
		if ((myChar > 47) && (myChar < 58 )) {inputInt = inputInt * 10 + myChar - '0';} //собираем число
	}
	if (stringComplete) { //если строка закончена
		pserial.println(inputInt); //отправляем её в порт для контроля
		if (sel == 1) {brnd = inputInt;} //в зависимости от селектора присваиваем переменным значение
		if (sel == 2) {speed = inputInt;}
		sel = 0; //выключаем селектор
		inputInt = 0; //обнуляем число
		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");
}

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Похоже не хватает оперативной памяти. Дописал код до полного функционала - вообще не работает.
Начал срезать по кускам - заработал. Причем куски по-отдельности - работают.

Сейчас буду переписывать и оставлять минимум глобальных переменных. Попробую построить программу на 2-3 переменных.

Хотя странно... у AtMega328p 1кБ ОЗУ - должно же хватать.

leshak
Offline
Зарегистрирован: 29.09.2011

Ну, для начала погуглите как измерять "сколько сейчас памяти есть". 

Во вторых, всякие строки в PROGMEM упихивать. Правда у вас тут длинных строк особо не видно, а перенос строк в пару символов особого выигрыша не дает, но.... похожими "пожирателями", могут выступить ширфты и "значек, значек, логотип...". Можно попытся их в PROGMEM , если они еще не там.

Попытатся заставить, все-таки, работатьь програмный Serial. Софтварный, он же тоже память кушать хочет...

Ну и оптимизации. Искать повторяющиеся куски, выделять их в функции. Или вещи типа:

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 ");}

свернуть как-то так:

char* dayNames[]={"Su","Mo","Tu","We","Th"....};

TVprint(81,65,dayNames[weekDay]);

и т.д. и т.п.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Про ОЗУ читал, но тогда не разобрался :) Надо видимо вникать. Сейчас поставлю IDE 1.5.6 r2 - посмотрю сколько памяти под переменные отводится. Ну и надо будет вникнуть в определение свободной ОЗУ.

Попробую для начала часть глобальных переменных сделать локальными.
+ есть мысль использовать вместо 10 переменных - 2: одну - для хранения числа, а вторую - для определения куда это число "рисовать". У меня ведь на экран графика выводится. Попробую не ряд мелких значков, а один крупный и перерисовывать его раз в несколько секунд, а данные выводить "поверх".

melvladimir
Offline
Зарегистрирован: 08.03.2013

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.

Говорю ж - должно хватать ОЗУ :) ерунда какая-то... буду ковыряться дальше

leshak
Offline
Зарегистрирован: 29.09.2011

Буквально вчерась отписывал в соседней ветке, что эти цифры по памяти - никакакого значения не имеют. Они могут подсказать только если есть явная и грубая попытка превысить. Скажем объявить массив размером мегабайта на два.

Узнать же, на этапе компиляции РЕАЛЬНЫЙ расход памяти - теоретически не возможно. Так что если тут говорит "занято не много" - это ничего не значит. Скажем  вызвала какая-то библиотека, malloc(someVars);  Глядя на этот вызов вы можете сказать сколько памяти израсходовалось?  Нет. Потому что не  знаете значение someVars на момент вызова. И компилятор - тоже не знает.

К сожалению, насколько я знаю ТОЧНО узнать расход памяти можно только с помощью JTAG дебагера :(  Ну или в эмуляторе (PROTEUS и т.п.) пытатся запустить.

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

Arduino Playground - AvailableMemory

В свое время перебирал их. Не помню какой, но только один мне начал выдавать что-то "правдоподбное" (объявляю пару строк - расход памяти увеличивается, убираю пару символов" - уменшается).

melvladimir
Offline
Зарегистрирован: 08.03.2013

Как раз это читаю сейчас.

Также бегло посмотрел pollserial - вроде как измененный аналог serial, т.е. аппаратный, а не программный.

Просто в программе и расчетов особо нет: взял переменную - показал. Насколько ждрет память "показал" - не известно. Но в то же время отображение и обновление значков - работает без глюков хоть весь день. Проблемы начинаются при попытке приема и обработки. Что наталкивает на мысль о "софтварности" serial. Копаю дальше.

leshak
Offline
Зарегистрирован: 29.09.2011

melvladimir пишет:

Хотя странно... у AtMega328p 1кБ ОЗУ - должно же хватать.

Похоже AtMega328 с вами не совсем согласна :(

Давайте посмотрим сколько же памяти нужно для одного пикселя этой библиотеке:

Смотрим https://code.google.com/p/arduino-tvout/source/browse/TVout/TVout.cpp

char TVout::begin(uint8_t mode, uint8_t x, uint8_t y) {
        
        // check if x is divisable by 8
        if ( !(x & 0xF8))
                return 1;
        x = x/8;
                
        screen = (unsigned char*)malloc(x * y * sizeof(unsigned char));
        if (screen == NULL)
                return 4;
                
        cursor_x = 0;
        cursor_y = 0;
        
        render_setup(mode,x,y,screen);
        clear_screen();
        return 0;
} // end of begin

То есть, на один пиксель нужен один байт.

Смотрим как вы вызываете эту функцию (какое у вас разрешение):

TV.begin(_PAL,144,81);

144*81=11664byte

То есть ~11.3кБ только на видеопамять у вас ушло.

Чисто из любопыства,  пустите, что-то типа

char errorCode=TV.begin(_PAL,144,81);

if(errorCode){
   Serial.begin(57600); 
   Serial.print("TV Init error=");
   Serial.prinln(errorCode,DEC);

  while(true); // остановили скетч
}

Что-нибудь выводит?

melvladimir
Offline
Зарегистрирован: 08.03.2013

Про 1байт/пиксель не совсем понял. В коде не рылся, т.к. бесполезно, вряд ли пойму, но когда рисовал шрифты и картинки, то 1 пиксель=1бит, т.е. строка типа 0b0001110 "включит" 3 пикселя. Или, например, код цифры 7:



0b11111000,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000,
0b00000000,
0b00000000,

Код минут через 30 попробую, правда не понял как он работает... Инициализация ТВ-выхода есть, но при этом код на экран ничего не "отрисовывает".

leshak
Offline
Зарегистрирован: 29.09.2011

Зачем рыться в коде? Ну например что-бы лучше понимать что происходит. Примеры же вы смотрите? Чем код библиотеки отличается от примеров? Тем более даже если там "зубодробительный код", то даже среди него можно найти понятные строки. Коментарии там почитать и т.п. Например описание что возвращает фунция TVOut.begin

В дан-ном же случае даже рыться не нужно. Я уже порылся за вас и привел вам сюда исходит функции.  И даже выделил жирным строку на которую нужно обратить внимание. Если непонятно что она делает, то осталось только загуглить что такое malloc() и прочитать ее описание. А потом прикинуть какое число ей передатся когда мы вызовем ее с x,y - 144,81

>Про 1байт/пиксель не совсем понял. 

В каком виде вы картинки кодируете - в данном случае рояля не играет. Важно то, в каком виде внутри себя, библиотека хранит данные о том что сейчас нарисованно на экране. А внутрях она для каждого пикселя выделяет байт. Почему целый байт - я не знаю. Может быть просто "лень было", может для скорости,  (выделяем байт, а используем только бит), может для того что-бы в градациях серого рисовать (скорее всего), может задел на будущую многоцветность.

Вообщем картинки у вас - действительно "однобитные". Черно-белые. А вот "видео-память" - "байт на пиксель".

о при этом код на экран ничего не "отрисовывает".

А этот код ничего и не должен отрисовыать. В Serial Monitor смотрите. Есть там надпись типа "TV init error=4"?

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Есть "TV init error=4". Сразу после старта.

Возможно многоцветность или оттенки серого планировались, но так и не были реализованы.
Вчера-сегодня переписывал код. Убрал по максимуму перепенные. Также попробую снизить разрешение до 128х72 точки.

ЗЫ: всё равно не понимю почему сдыхает при передаче инфы. Ведь: "pollserial.h Heavily modified version of:
HardwareSerial.h - Hardware serial library for Wiring". Пока не передаешь - работает, читает 2 аналоговых порта, отображает время, всё это красиво рисует...

melvladimir
Offline
Зарегистрирован: 08.03.2013

По-моему я нашел ось зла: часики...
Загрузил переписанный код, где минимальное кол-во переменных, 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.

Ах, да, код сейчас выглядит так (используется одна переменная для приема символов, другая для сбора из символов числа и третья - для определения в какое место экрана выводить собранное число):



#include <TVout.h> //библиотека TVout
#include <font6x8.h> //основной шрифт для ТВ
#include <font8x12.h> //увеличенный шрифт для спидометра, только цифры
#include "fuellvl.h" //значок уровня топлива
#include "l100km.h" //значок мл/100км
#include "mlhour.h" //значок мл/час
#include "temp.h" //значок температуры
#include "trip.h" //значок одометра
#include <pollserial.h>
pollserial pserial;
TVout TV;
volatile unsigned long inputInt = 0; //для собирания числа из цифр
unsigned long prev_s=0; //переменная для вычисления отрезков времени
int T=0; //температура
int F=0; //уровень топлива
int sel; //определитель переменной, которой присваивается переданное значение
boolean stringComplete = false; //метка окончания передачи
char myChar = 0; //для принятия символа из буфера

void setup()
{
TV.begin(_PAL,144,81); //формат и разрешение
TV.select_font(font6x8); //выбор основного шрифта
TV.set_hbi_hook(pserial.begin(57600)); //толком не знаю что это, взято из примера на сайте библиотеки TVout, отвечает за связь
Temp(); //получение, расчет и вывод температуры на экран
FuelLevel(); //получение, расчет и вывод уровня топлива на экран
}

void loop() {
	if (pserial.available()) { //если есть данные в буфере
		delay(3);
		myChar = (char)pserial.read(); //считываем байт
		if (myChar == '\n') {stringComplete = true;} //если пришло окончание строки, то ставим метку
		else {
			if ((myChar > 47) && (myChar < 58 )) {inputInt = inputInt * 10 + myChar - '0';} //собираем число
			else {
				if (myChar == 'B') {sel = 1;} //brnd - сожжено топлива
				if (myChar == 'V') {sel = 2;} //speed - скорость
				if (myChar == 'M') {sel = 7;} //сообщение
				if (myChar == 'D' && sel == 7) {sel = 8;} //сообщение о сохранении данных
				if (myChar == 'E' && sel == 7) {sel = 9;} //сообщение "можно стартовать"
				if (myChar == 'S') {sel = 3;} //distance - одометр
				if (myChar == 'H') {sel = 4;} //aver_h - мгновенный расход в час
				if (myChar == 'F') {sel = 5;} //aver_100 - мгновенный расход на 100км
			}
		}
	}
	if (stringComplete) { //если строка закончена
		if (sel > 0) {
			if (sel == 1) {Brnd();} //в зависимости от селектора присваиваем переменным значение
			if (sel == 2) {Speed();}
			if (sel == 3) {Trip();}
			if (sel == 4) {FuelAverH();}
			if (sel == 5) {FuelAver1();}
			if (sel == 8) {Saved();}
			if (sel == 9) {Ready();}
			sel = 0; //выключаем селектор
		}
		inputInt = 0; //обнуляем число
		stringComplete = false; //убираем метку
	} else {
		if (((millis() / 1000) - prev_s) >= 25) { //создает временные отрезки, чтобы распределить нагрузку
		prev_s = (millis() /1000);
		Temp(); //получение, расчет и вывод температуры на экран
		FuelLevel(); //получение, расчет и вывод уровня топлива на экран
		}
	}
}
void Saved() {
	TV.clear_screen();
	TV.print(18,0, "All Data Saved");
	TV.print(24,10, "Successfully");
	TV.print(30,20, "60 seconds");
	TV.print(12,30, "to switching off");
}
void Ready() {
	TV.clear_screen();
	TV.print(0,20, "Ready to Start");
}
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 Speed(){
	TV.select_font(font8x12); //смена шрифта на большой и вывод скорости
	TV.print(55,22, "///");
	if (inputInt > 99) {TV.print(55,22, inputInt);}
	else {
		if (inputInt > 9) {TV.print(59,22, inputInt);}
		else {TV.print(63,22, inputInt);}
	}
	TV.select_font(font6x8);
	TV.print(56,34, "km/h");
}
void FuelAverH(){
	if (inputInt > 9999) {TV.print(0,2, inputInt);}
	else {
		if (inputInt > 999) {TV.print(6,2, inputInt);}
		else {
			if (inputInt > 99) {TV.print(12,2, inputInt);}
			else {
				if (inputInt > 9) {TV.print(18,2, inputInt);}
				else {
					TV.print(24,2, inputInt);
				}
			}
		}
	}
	TV.bitmap(31,0,mlhour);
}
void FuelAver1(){
	if (inputInt > 9999) {TV.print(0,2, inputInt);}
	else {
		if (inputInt > 999) {TV.print(6,2, inputInt);}
		else {
			if (inputInt > 99) {TV.print(12,2, inputInt);}
			else {
				if (inputInt > 9) {TV.print(18,2, inputInt);}
				else {
					TV.print(24,2, inputInt);
				}
			}
		}
	}
	TV.bitmap(31,0,l100km);
}
void Trip() {
	TV.bitmap(0,58,trip); //вывод расстояния
	TV.print(14,56, inputInt);
	TV.print("m");
}
void Brnd() {
	TV.print(76,2, "     ");
	if (inputInt > 99999) { //вывод кол-ва израсходованного топлива
		TV.print(76,2, inputInt);}
		else {
			if (inputInt > 9999) {TV.print(82,2, inputInt);}
			else {
				if (inputInt > 999) {TV.print(88,2, inputInt);}
				else {
					if (inputInt > 99) {TV.print(94,2, inputInt);}
					else {
						if (inputInt > 9) {TV.print(100,2, inputInt);}
						else {
							TV.print(106,2, inputInt);
						}
					}
				}
			}
		}
	TV.print("ml");
}

Сейчас попробую измерить свободную ОЗУ и буду переходить к тестированию работы двух МК в связке. И потом надо будет решать вопрос с датой и временем...

melvladimir
Offline
Зарегистрирован: 08.03.2013

По ссылке 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

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

leshak
Offline
Зарегистрирован: 29.09.2011

melvladimir пишет:

Есть "TV init error=4". Сразу после старта.

Печалька. Теперь смотрим в файлик https://code.google.com/p/arduino-tvout/source/browse/TVout/TVout.cpp

И читаем что означает код возврат из TvOut.begin 

 

/* call this to start video output with a specified resolution.
 *
 * Arguments:
 *      mode:
 *              The video standard to follow:
 *              PAL             =1      =_PAL
 *              NTSC    =0      =_NTSC
 *      x:
 *              Horizonal resolution must be divisable by 8.
 *      y:
 *              Vertical resolution.
 *
 *      Returns:
 *              0 if no error.
 *              1 if x is not divisable by 8.
 *              2 if y is to large (NTSC only cannot fill PAL vertical resolution by 8bit limit)
 *              4 if there is not enough memory for the frame buffer.
 */

Правда, если посмотреть в код, ошибки (1) и (2) там никогда вернутся не могут. А вот return 4 - имеется.

И возвращается именно когда не удалось выделить память под видео-буффер. В резульатте этого буффер (поле screen) - имеет значение null. render_setup() - не выполнился.

Далее, фактически, все попытки что-то рисовать/писать пишут/меняют не выделенный указатель. Куда-то "в начало памяти". Что там окажется по этим адресам, что перезапишется/перетрется или поменяется другими библиотеками - никто не знает. Чисто как повезет. Могут чужие данные там оказатся, может код самого скетча....

Поэтому подбирать кто там виноват в троице "TVout+Wire+Serial" - не имеет смысла. Виновник известен - TVOut которому не хватило памяти, мы это не проверили, но заставили работать. Врезультате он работает в режиме "на кого попало". И ловить можно совершенно разные и мистические глюки. И долго перебирать комбинации "что-бы работало". Но даже если "заработло", то это совершенно не означет что будет работать. От чиха все рухнет. Скажем первая цифра текущего времени 3 - может работать, и 8 - мь все осыпится....

Вообщем этом как в машине. Вода в масле. Амальгама. Вроде завелся, но когда поймает клин - никому не ведомо.

При этом лампочка что давления масла нет - горит (код ошибки 4-ре).

leshak
Offline
Зарегистрирован: 29.09.2011

melvladimir пишет:

Таким образом возможно причина не в конфликте библиотек, а таки в нехватке памяти, но и конфликт исключать не стоит.

Не возможно, а "так и есть". А причина конфликта - нехватка памяти.

Почему у вас это вызывает сомнение, непонятно. Сообщении 17-ть я вам привел код функции begin, которую вы вызваете. Посмотрите на него. Ничего сверх-сложного в нем нет. Поведение - очевидно. И предсказуемо если взять калькулятор и умножить 144 на 81.

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

Есть вероятность, что я ошибаюсь, но..... возвращенный код 4 говорит об обратном. Может быть это остатки какого старого кода, который уже не используется..., но другого, который работает не через этот буффер screen - я не вижу в коде. 

Да и само наличие "глюков не объяснимых" говорит что, все-таки, к сожалению, я прав.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Спасибо за помощь и детальное разъяснение!
Контрольная проверка свободной памяти практически это же показало.
Сейчас буду думать над вариантами и тестировать...
В конце-концов, могу попробовать поменять местами Mega2560 и Mini Pro, да и еще не пробовал снизить разрешение. А время могу передавать также, как и другие переменные - через serial.

Еще раз спасибо! А то задолбался уже :) знаний не хватает, но очень хочется...

leshak
Offline
Зарегистрирован: 29.09.2011

К сожалению на ~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 шине хватит скорости.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Одно бесспорно радует: 3 часа работает Mini Pro, периодически кидаю ему данные для отображения и принимаю инфу о свободной памяти. Всё ОК. При этом не стесняюсь кормить его на всю емкость переменной unsigned long (без фанатизма, т.к., например, под скорость отведено 3 знака, ну можно 6 втулить, но больше - перекосит картинку). Также периодически чищу экран путем вывода "зашитых" сообщений, перед которыми выполняется очистка экрана.

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

leshak
Offline
Зарегистрирован: 29.09.2011

Ну, как я уже говроил, это "работает" - чистно на везении. Когда и от чего заглючит - нередсказуемо.

 

leshak
Offline
Зарегистрирован: 29.09.2011

Кстати, если будете уменьшать разрешение, то не забудте, что "Horizonal resolution must be divisable by 8."

Хоть в begin и нет проверки на это (но явно планировалось), дальше по коду много где это предполагается. Кратность 8-ми.

И в коде таки видно, что по крайней мере планировась (возможно уже и доделано), что разрешение может быть меньше чем PAL/SECAM. Видны переменные для маштабирования. По крайней мере по y-ку увидел.

Возможно там и по x-су есть, но там уже ассемблерные вставки :(. А я с ассемблером, последний раз общался в начале 90-тых. И то... парочка программ на 20-30 строк.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Разрешение я испробовал одним из первых :) так сказать - методом тыка (но в пропорциях и с кратностью 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 часов подряд - всё ОК.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Сказано - сделано :) Тот же код залит в 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Б спишем на погрешность работы измерялок и/или разность в МК, всё таки библиотеки используются, а не полностью правильный код).
Всё, можно теперь спокойно отдохнуть :)

leshak
Offline
Зарегистрирован: 29.09.2011

>Также вселяет надежду и остаток свободной памяти - 273Б,

Не на отчеты freeMemory() смотреть нужно, а на то что вам вернула TVOut.begin(). Пока она не вернет ноль - ни о какой стабильности речи быть не может. Если вернула ноль - значит она смогла выделить память под запрошенное разрешение. Хватило. И эта память уже будет "занята ей". Другие библиотеки в нее не полезут читать/писать. И она записывая туда - никому не повредит.

А пока она возращает 4-ре, значит память выделить не удалось. Вы радостно смотрите на freeRam(), которая показывает что память не занята... Конечно не занята раз зарезирвировать ее для нужд TVOut не вышло. 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Больше склоняюсь к ошибке в библиотеке. Т.к. 1 байт на пиксель - это много для ч/б. Это уже 256 оттенков серого или 256 цветов.
У какого МК из этого перечня: "m168, m328, m1280, m2560, m644, m1284p" есть 128*96=12228Б + переменные = 16кБ ОЗУ? Ни у какого. А все они работают с ТВ-выходом на "стандартном" разрешении.
Для чего в библиотеке та драконовская функция - не ясно. Возможно для рисования "динамической" графики типа "тетриса", появление и исчезания геометрических фигур и др.

leshak
Offline
Зарегистрирован: 29.09.2011

#$@#$@#$#$!!!!!!!!!!!!!!!!!!!!!!!!!

Так да... бит на пиксель.

Всего-то на строчку выше глянуть нужно было

char TVout::begin(uint8_t mode, uint8_t x, uint8_t y) {
        
        // check if x is divisable by 8
        if ( !(x & 0xF8))
                return 1;
        x = x/8;
                
        screen = (unsigned char*)malloc(x * y * sizeof(unsigned char));
        if (screen == NULL)
                return 4;
                
        cursor_x = 0;
        cursor_y = 0;
        
        render_setup(mode,x,y,screen);
        clear_screen();
        return 0;
} // end of begin

То есть, не 144*81=11664byte нужно, а (144/8)*81=1458 байт. Что, в случае с мегой - уже выглядит вполне реально. И с 328 - тоже реально, если только уже в своем скетче скромно вести себя по поводу памяти.

Сдругой стороны, не полезли бы смотреть в код, не увидили бы что есть код возврата 4 означающий нехватку памяти. А он у нас таки был.

Так что добиватся того что-бы TVOut.begin возвращал ноль - все равно нужно. Но теперь это выглядит более/менее реальной целью ;)

art100
Offline
Зарегистрирован: 09.03.2014

так когда ждать  для 20$ ???

 а то у меня тут не влезает

мне пожалйсто в SEKAM кодировке со звуком DolbyDigital5.1 вполне устроит

еще не плохо чтоб по web-интерфейсу управлялся ну и XBMC работал

неплохо H.264 раскодировочку добавить хотябы с MPEG2

ну и кардшаринг от моего легального dreambox7000

и еще неплохобы азимут угламеста потому как на тарелках моторы уже есть


{0x00,0x00,0x00,0x1F,0x00,0x00,0x00},

{0x00,0x00,0xC0,0x3F,0x00,0x00,0x00},

{0x00,0x00,0xE0,0x7F,0x00,0x00,0x00},

{0x00,0x00,0xF8,0x9F,0x01,0x00,0x00},

{0x00,0x00,0xFC,0xFF,0x07,0x00,0x00},

{0x00,0x1C,0xFE,0xFF,0x1F,0x00,0x00},

{0x00,0x12,0xFE,0xFF,0x7F,0x00,0x00},

{0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00},

{0x00,0x20,0xF7,0xFF,0xFF,0x01,0x00},

{0x00,0xC2,0xF1,0xFF,0xFF,0x00,0x00},

{0x00,0x80,0xF9,0xFF,0xFF,0x01,0x00},

{0x00,0x00,0xF9,0xFF,0xFF,0x01,0x00},

{0x00,0x00,0xF0,0xFC,0xFF,0x01,0x00},

{0x00,0x20,0x60,0xFE,0xFF,0x01,0x00},

{0x00,0x80,0xFF,0xFF,0xFF,0x00,0x00},

{0x00,0x80,0xFF,0xFF,0x7F,0x00,0x00},

{0x00,0x00,0xFF,0xFF,0x3F,0x00,0x00},

{0x00,0x00,0xFC,0xDF,0x1F,0x00,0x00},

{0x00,0x00,0xFA,0xCF,0x07,0x00,0x00},

{0x00,0x00,0xE0,0xFF,0x07,0x00,0x00},

{0x00,0x80,0xE0,0xEF,0x1B,0x00,0x00},

{0x00,0x80,0xC0,0xFF,0x03,0x00,0x00},

{0x00,0x80,0xC1,0x7F,0x03,0x00,0x00},

{0x00,0x80,0xC1,0xFF,0x0B,0x00,0x00},

{0x00,0x00,0xC3,0xFF,0x13,0x00,0x00},

{0x00,0x00,0xC2,0xFF,0x27,0x00,0x00},

{0x00,0x00,0xEC,0xFF,0x1F,0x00,0x00},

{0x00,0x00,0xF8,0xFF,0x0F,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x40,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00},

{0x00,0x40,0xE0,0xFF,0x07,0x00,0x00},

{0x00,0x04,0x00,0x7E,0x00,0x00,0x00},

{0x00,0x38,0x00,0x7E,0x00,0x00,0x00},

{0x00,0x30,0xC0,0xFF,0x03,0x00,0x00},

{0x00,0x70,0x60,0xFF,0x07,0x00,0x00},

{0x00,0x70,0x30,0xFC,0x1F,0x00,0x00},

{0x00,0xE0,0x9C,0xFD,0x3F,0x00,0x00},

{0x00,0xE0,0x9F,0xFD,0x7F,0x00,0x00},

{0x00,0xC0,0xBF,0xFC,0xFF,0x01,0x00},

{0x00,0x00,0x70,0xFF,0xE7,0x03,0x00},

{0x00,0x00,0xF0,0xFF,0x87,0x03,0x00},

{0x00,0x00,0xF0,0xFF,0x07,0x07,0x00},

{0x00,0x00,0xF0,0xFF,0x07,0x07,0x00},

{0x00,0x00,0xE0,0xFF,0xC7,0x03,0x00},

{0x00,0x00,0xF0,0xFF,0xE7,0x01,0x00},

{0x00,0x00,0xF0,0xFF,0xF7,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x47,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x23,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x03,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x83,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x07,0x00,0x00},

{0x00,0x00,0xF0,0xFF,0x07,0x04,0x00},

{0x00,0x00,0xF0,0xFF,0x0F,0x02,0x00},

{0x00,0x00,0xE0,0xFF,0x87,0x01,0x00},

{0x00,0x00,0xE0,0xFF,0x07,0x00,0x00},

{0x00,0x00,0xC0,0xFF,0x03,0x00,0x00},

{0x00,0x00,0xC0,0x01,0x03,0x00,0x00},

{0x00,0x00,0xC0,0x01,0x06,0x00,0x00},

{0x00,0x00,0x80,0x01,0x06,0x00,0x00},

{0x00,0x00,0x80,0x03,0x06,0x00,0x00},

{0x00,0x00,0x80,0x03,0x0C,0x00,0x00},

{0x00,0x00,0x80,0x03,0x0C,0x00,0x00},

{0x00,0x00,0x00,0x07,0x1C,0x00,0x00},

{0x00,0x00,0x00,0x07,0x18,0x00,0x00},

{0x00,0x00,0x00,0x07,0x38,0x00,0x00},

{0x00,0x00,0x00,0x07,0x78,0x00,0x00},

{0x00,0x00,0x00,0x0F,0x98,0x6C,0x00},

{0x00,0x00,0x80,0x18,0xC4,0x82,0x00},

{0x00,0x00,0xFE,0x3F,0x62,0x00,0x01},

{0x00,0x00,0x41,0x40,0x02,0x00,0x02},

{0x00,0x80,0x00,0x00,0x04,0x00,0x06},

{0x00,0x00,0x00,0x40,0x1E,0x00,0x07},

{0x00,0x40,0x00,0x78,0xF8,0xC1,0x01},

{0x00,0x60,0x00,0x3F,0xE0,0xFF,0x00},

{0x00,0xC0,0xFF,0x03,0x00,0x5C,0x00},

{0x00,0x00,0x3A,0x00,0x00,0x00,0x00},

 

преспрашиаю для непонятливых

8 бит и меньше мозга чем у Sinclair ZX Spectrum 64kbye CGA с магнитофоном с постоянной подкачкой кода. ~80$+80рублей

ВЧ модуль вижу у вас уже распаян на ардуине надо только вон к володку памяти поболее 64кбайт воткнуть Интеграл 256кбайтку выпустил можно вынести говорят ну или по блату ичкать когда супер 1мегабайт из англии кто-нибудь привезет

если мутно дебило графики вы еще сможете получить

то такой уровень графики 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$

 

 

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Всю простыню не осилил :)
К чему сей "опус"? Желаемый результат был достигнут и меня всё устраивает. Еще немножко дописать и будет всё "в ёлочку".

art100
Offline
Зарегистрирован: 09.03.2014

melvladimir пишет:

...результат был достигнут ...

поподробней можно?

melvladimir
Offline
Зарегистрирован: 08.03.2013

Результат - это вывод нужных данных на экран, без зависания, задержек, мерцания.

Есть бортовой комп. в автомобиле. Есть 4,3" экран с двумя тв-входами. "ТВ-выход" не любит частые и множественные прерывания, к тому же влияет на работу millis(). Взял Mini Pro для вывода данных с борт. компа на экран. Несколько дней мучился переписывая так и сяк код, потом создал эту тему, пришли гуру и натыкали носом в ошибки и помогли вникнуть в работу библиотеки. Ряд ошибок устранил и уже Mini Pro нормально принимает данные и отображает на экране. Надо еще чуть полирнуть и будет так, как задумывалось и даже круче :)

toc
Offline
Зарегистрирован: 09.02.2013

melvladimir, фотку покажите?

melvladimir
Offline
Зарегистрирован: 08.03.2013

Фотка с телека, в машину МК пока не ставил, надо еще дописать вывод нескольких параметров + хочу меню сделать.

А в приборке экран выглядит так (это старая фотка, как видно по дате, первое тестирование):

 mueqd07.jpg

art100
Offline
Зарегистрирован: 09.03.2014

понятно

хоть терминал

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Чуть переделал прием данных: теперь есть числовые и строковые данные, хотя и то и другое передается символами, а не байтами. С байтами не дружу, хотя может байтами таки проще и/или эффективнее.
Так дробные и/или отрицательные числа идут в виде набора символов, собираются в строку и строка выводится на экран. Немного щаз подзавис с передачей даты/времени... хотел сделать передачу только тех данных, которые изменились, а потом вспомнил, что у меня бывает условие очистки экрана и вывода текста и если возобновить работу МК, то на экран будет отрисовываться минуты, а остальное - надо долго ждать :) Надо чуть переписать :)

На данный момент протестирована работа нижеследующего кода (может кому пригодится). По-сути Mini Pro работает как "контроллер экрана" с единственной задачей - вывод данных на экран и всё.

#include <TVout.h> //библиотека TVout
#include <font6x8.h> //основной шрифт для ТВ
#include <font8x12.h> //увеличенный шрифт для спидометра, только цифры
#include "fuellvl.h" //значок уровня топлива
#include "l100km.h" //значок мл/100км
#include "mlhour.h" //значок мл/час
#include "temp.h" //значок температуры
#include "trip.h" //значок одометра
#include "ford.h" //большой логотип Ford
#include "inside.h" //надпись "внутри"
#include "outside.h" //надпись "снаружи"
#include <pollserial.h>
pollserial pserial;
TVout TV;
volatile unsigned long inputInt = 0; //для собирания числа из цифр
int sel; //определитель переменной, которой присваивается переданное значение
boolean stringComplete = false; //метка окончания передачи
char myChar = 0; //для принятия символа из буфера
char charArray[10]; //для сбора строки и вывода на экран

void setup()
{
TV.begin(_PAL,144,81); //формат и разрешение
TV.select_font(font6x8); //выбор основного шрифта
TV.set_hbi_hook(pserial.begin(57600)); //толком не знаю что это, взято из примера на сайте библиотеки TVout, отвечает за связь
}

void loop() {
	if (pserial.available()) { //если есть данные в буфере
		delay(3);
		myChar = (char)pserial.read(); //считываем байт
		if (myChar == '\n') {stringComplete = true;} //если пришло окончание строки, то ставим метку
		else {
			if ((myChar > 47) && (myChar < 58 )) {inputInt = inputInt * 10 + myChar - '0';} //собираем число
			else {
				switch(myChar) {
					case 'A': sel = 10; break; //минуты
					case 'B': sel = 1; break; //brnd - сожжено топлива
					case 'C': sel = 11; break; //часы
					case 'D': sel = 8; break; //сообщение о сохранении данных
					case 'E': sel = 9; break; //сообщение "можно стартовать"
					case 'F': sel = 5; break; //aver_100 - мгновенный расход на 100км
					case 'H': sel = 4; break; //aver_h - мгновенный расход в час
					case 'I': TempIn(); break; //внутренняя температура
					case 'L': sel = 16; break; //уровень топлива
					case 'O': TempOut(); break; //наружная температура
					case 'S': sel = 3; break; //distance - одометр
					case 'T': Temp(); break; //температура двигателя
					case 'U': sel = 17; break; //очистка экрана
					case 'V': sel = 2; break; //speed - скорость
					case 'W': sel = 14; break; //день недели
					case 'X': sel = 12; break; //числа месяца
					case 'Y': sel = 15; break; //год
					case 'Z': sel = 13; break; //месяц
				}
			}
		}
	}
	if (stringComplete) { //если строка закончена
		if (sel > 0) {
			switch(sel) {
				case 1: Brnd(); break;
				case 2: Speed(); break;
				case 3: Trip(); break; //distance - одометр
				case 4: FuelAverH(); break; //aver_h - мгновенный расход в час
				case 5: FuelAver1(); break; //aver_100 - мгновенный расход на 100км
				case 8: Saved(); break; //сообщение о сохранении данных
				case 9: Ready(); break; //сообщение "можно стартовать"
				case 10: Minutes(); break;
				case 11: Hours(); break;
				case 12: Days(); break;
				case 13: Month(); break;
				case 14: Week(); break;
				case 15: Year(); break;
				case 16: FuelLevel(); break;
				case 17: TV.clear_screen(); break;
			}
			sel = 0; //выключаем селектор
		}
		inputInt = 0; //обнуляем число
		stringComplete = false; //убираем метку
	}
}
void Saved() {
	TV.clear_screen();
	TV.print(18,0, "All Data Saved");
	TV.print(24,10, "Successfully");
	TV.print(30,20, "60 seconds");
	TV.print(12,30, "to switching off");
}
void Ready() {
	TV.clear_screen();
	TV.bitmap(9,5,ford);
	TV.print(30,65, "Ready to Start");
}
void Speed(){
	TV.select_font(font8x12); //смена шрифта на большой и вывод скорости
	TV.print(61,29, "///");
	if (inputInt > 99) {TV.print(61,29, inputInt);}
	else {
		if (inputInt > 9) {TV.print(65,29, inputInt);}
		else {TV.print(69,29, inputInt);}
	}
	TV.select_font(font6x8);
	TV.print(62,41, "km/h");
}
void FuelAverH(){
	if (inputInt > 9999) {TV.print(1,3, inputInt);}
	else {
		if (inputInt > 999) {TV.print(7,3, inputInt);}
		else {
			if (inputInt > 99) {TV.print(13,3, inputInt);}
			else {
				if (inputInt > 9) {TV.print(19,3, inputInt);}
				else {
					TV.print(25,3, inputInt);
				}
			}
		}
	}
	TV.bitmap(32,1,mlhour);
}
void FuelAver1(){
	if (inputInt > 9999) {TV.print(1,3, inputInt);}
	else {
		if (inputInt > 999) {TV.print(7,3, inputInt);}
		else {
			if (inputInt > 99) {TV.print(13,3, inputInt);}
			else {
				if (inputInt > 9) {TV.print(19,3, inputInt);}
				else {
					TV.print(25,3, inputInt);
				}
			}
		}
	}
	TV.bitmap(32,1,l100km);
}
void Trip() {
	TV.bitmap(1,67,trip); //вывод расстояния
	TV.print(16,65, inputInt);
	TV.print("m");
}
void Brnd() {
	TV.print(95,3, "     ");
	if (inputInt > 99999) { //вывод кол-ва израсходованного топлива
		TV.print(95,3, inputInt);}
		else {
			if (inputInt > 9999) {TV.print(101,3, inputInt);}
			else {
				if (inputInt > 999) {TV.print(107,3, inputInt);}
				else {
					if (inputInt > 99) {TV.print(113,3, inputInt);}
					else {
						if (inputInt > 9) {TV.print(119,3, inputInt);}
						else {
							TV.print(125,3, inputInt);
						}
					}
				}
			}
		}
	TV.print("ml");
}
void Minutes(){
	if (inputInt < 10) {TV.print("0"); TV.print(131,74,inputInt);}
		else {TV.print(131,74,inputInt);}
}
void Hours(){
	if (inputInt < 10) {TV.print(113,74,"0"); TV.print(inputInt);}
		else {TV.print(113,74, inputInt);}
	TV.print(":");
}
void Days(){
	if (inputInt < 10) {TV.print(95,65, "0"); TV.print(inputInt);}
		else {TV.print(95,65, inputInt);}
}
void Month(){
	TV.print(107,65, ".");
	if (inputInt < 10) {TV.print("0"); TV.print(inputInt);}
		else {TV.print(inputInt);}
}
void Week(){
	char* dayNames[]={"Mo","Tu","We","Th","Fr","Sa","Su"};
	TV.print(95,74,dayNames[(inputInt-1)]);
}
void Year(){
	TV.print(125,65,".");
	TV.print(inputInt);
}
void TempIn() {
int i = 0;
    while (pserial.available())            //если есть что читать
    {
        delay(3);
        charArray[i] = pserial.read();     //читаем символ в массив
        if (charArray[i] == '\n')         //если считали символ переноса каретки (строка закончилась)
        {
            charArray[i] = '\0';        //ставим пустой символ (завершение строки)
			TV.bitmap(1,43,inside);
            TV.print(1,51, "        ");     //выводим строку
            TV.print(1,51, charArray);     //выводим строку
			TV.print("*C");
		}
        i++;
    }
}
void TempOut() {
int i = 0;
    while (pserial.available())            //если есть что читать
    {
		delay(3);
		charArray[i] = pserial.read();     //читаем символ в массив
		if (charArray[i] == '\n')         //если считали символ переноса каретки (строка закончилась)
		{
			charArray[i] = '\0';        //ставим пустой символ (завершение строки)
			TV.bitmap(1,20,outside);
			TV.print(1,28, "        ");
			TV.print(1,28, charArray);     //выводим строку
			TV.print("*C");
		}
		i++;
	}
}
void Temp() {
	TV.bitmap(100,42,temp);
	int i = 0;
    while (pserial.available())				//если есть что читать
    {
        delay(3);
        charArray[i] = pserial.read();     //читаем символ в массив
        if (charArray[i] == '\n')         //если считали символ переноса каретки (строка закончилась)
        {
            charArray[i] = '\0';        //ставим пустой символ (завершение строки)
            TV.print(119,47, charArray);     //выводим строку
        }
        i++;
    }
}
void FuelLevel(){ //уровень топлива
	TV.bitmap(105,19,fuellvl);
	TV.print(127,19, inputInt);
	TV.print(" ");
}

А выглядит на экране это так:

melvladimir
Offline
Зарегистрирован: 08.03.2013

Еще не подключил датчики температуры и RTC модуль, но остальные данные передаются и отображаются четко.

Ну и еще надо доделать вывод меню и др., но на работу не повлияет.

ds6328
Offline
Зарегистрирован: 03.05.2015

Привет, не понятно как ты получаешь данные с авто, я так понимаю без OBD? У меня не получается одновременная работа на ардуине TVOut и ELM327-блютуз.

ds6328
Offline
Зарегистрирован: 03.05.2015

melvladimir пишет:

Еще не подключил датчики температуры и RTC модуль, но остальные данные передаются и отображаются четко.

Ну и еще надо доделать вывод меню и др., но на работу не повлияет.

Привет, не понятно как ты получаешь данные с авто, я так понимаю без OBD? У меня не получается одновременная работа на ардуине TVOut и ELM327-блютуз.

lemnomel
Offline
Зарегистрирован: 03.12.2015

Привет!
Исходниками не поделитесь?
Не думали доработать проект под возможность использования в режиме Osd, то есть выводить данные поверх видеосигнала с камеры заднего вида?

ds6328
Offline
Зарегистрирован: 03.05.2015

Я считаю незачем данные выводить поверх видео с КЗВ.

lemnomel
Offline
Зарегистрирован: 03.12.2015

Кому как, такой вариант думаю заинтересовал бы квадрокоптеров. Хозяин то пропал? Ds6328 может у тебя есть исходники?

ds6328
Offline
Зарегистрирован: 03.05.2015

У меня нет таких данных, я щас делаю отображение данных по блютузу от ELM327 на ардуину с монитором. 

lemnomel
Offline
Зарегистрирован: 03.12.2015

Получается? Ознакомиться с результатами можно?