Помогите с кодом.

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

Доброго всем времени суток.

Нужна помощь с кодом:

Есть dataFile в котором хнанится значение raw в формате Char (точнее значение храниться в документе на флешке и считываеться в dataFile) 

это значение Char нужно перевести в unsigned int для вставки значения.

unsigned int irSignal[67] ={тут значение Char};

в оригинале значения raw равны (4550,4450, 600,1650, 550,1700, 600,1650, 550,550, 600,550, 550,550, 550,550, 600,550, 550,1700, 550,1700, 550,1650, 550,600, 550,550, 550,600, 550,550, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,600, 550,550, 550,550, 600,550, 550,1700, 550,550, 550,550, 600,550, 550,1700, 550,1650, 600,1650, 550,1700, 600)

Занимаюсь Arduino не так давно поэтому возникают проблемы в программировании.

Заранее спасибо.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Проблема, как прочитать из файла данные? См. методы класса File.

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

Проблема именно перевести значение в unsigned int. Я далек от програмирования, Недавно только начал изучать ардуино. 

вот кусок моего кода 

File dataFile = SD.open(String(val,DEC)); // Открываем файл 
if (dataFile) {
while (dataFile.available()) { // Проверяем что файл не пустой
Serial.write(dataFile.read()); // выводим содержимое в сериал 
unsigned int irSignal[67] = {тут нужно вставить значение из dataFile} ; // Тут вставляем raw код из datafile
irsend.sendRaw(irSignal, 67, 38); 

SD.open открывает текстовый файл на флешке в котором записано значение raw
в каждом файле содержится одинаковое содержимое вида 

4550,4450, 600,1650, 550,1700, 600,1650, 550,550, 600,550, 550,550, 550,550, 600,550, 550,1700, 550,1700, 550,1650, 550,600, 550,550, 550,600, 550,550, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,600, 550,550, 550,550, 600,550, 550,1700, 550,550, 550,550, 600,550, 550,1700, 550,1650, 600,1650, 550,1700, 600

код кнопки.

тоесть при отправке определенной команды, на флешке открывается определенный файл, его содержимое считывается и это содержимое нужно вставить в 

unsigned int irSignal[67] = {тут нужно вставить значение} ;
для отправки этого содержимого.

беда в том что dataFile считываеться как значение char в терминале все супер.

проблема именнов вставить значение в unsigned int arduino выдает ошибку что необходимо перевести char в unsigned int, к несчастью я не знаю как это сделать. пробовал разные варианты конвертации но тогда значение на выходе меняется или запятые или сами числа.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

У вас в файле данные в текстовом виде, как вы указали, т.е. 4550,4450, и т.д.? Или в бинарном?

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

обычный текст 

таких файлов около 50 пока.

в дальнейшем будут добавлены еще пара сотен.

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

Суть проекта универсальный пульт от всего, что только возможно! В файлах на шлешке хранятся raw кнопок. Принцип 1 устройством управлять всем Tv / Копдиционер / чайник / и тд. С возможностью добавить новые устройства путем простого копирования файла со считаным raw. По большей части я уже сделал то что хотел но код не влезает на arduino (Рабочий код получился на 90 000 байт и глобальные переменные на 6 000 примерно). поэтому было принято скинуть часть с raw на карту sd. Все получилось на ура за исключением того что я немогу теперь вставить значение из dataFile если написать unsigned int irSignal[67] = {dataFile}; то приходит не код со структурой как в файле Типа

4550,4450, 600,1650, 550,1700, 600,1650, 550,550, 600,550, 550,550, 550,550, 600,550, 550,1700, 550,1700, 550,1650, 550,600, 550,550, 550,600, 550,550, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,600, 550,550, 550,550, 600,550, 550,1700, 550,550, 550,550, 600,550, 550,1700, 550,1650, 600,1650, 550,1700, 600

а каша по принципу

26546546545454654654543214356344556421572245574155447524455674234456542465546254356253454

24562544565642654546725645245652445546652445564254546542456524455462545467254478455645435

5475442543546245546265445652434556424541264345654245564625464566524456546246556465

которую мне и нужно победить.

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

если raw прописан принудительно то все работает.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Вот смотрите, какой алгоритм работы вам нужен:

1. Открываем файл.

2. Заводим локальный буфер под строковое представление числа (пусть это будет String buff;)

3. Посимвольно читаем из файла.

4. Смотрим - это символ ','  ?

5. Не запятая? Складываем прочитанный символ в буфер.

6. Запятая? Смотрим - если в буфере чего-то есть - переводим его в число. Очищаем буфер. Получившееся число сохраняем по текущему индексу записи в массив. Инкрементируем индекс записи в массив.

7. Достигнут конец файла? Вываливаемся из цикла.

8. Если в буфере чего-то есть - переводим его в число. Получившееся число сохраняем по текущему индексу записи в массив.

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

local buffer, file, resultArray = new integer[50], writePointer = 0;

with file.open("raw.txt") do

	local char = file.read()
	
	if char is ',' then
		if not empty(buffer) then
			local int = convert.toInt(buffer)
			clear(buffer)
			resultArray[writePointer] = int
			increment(writePointer)
			
		endif
	else if char between '0' and '9' then
		concat(buffer,char)
	endif
	
	if file.eof() then exit while

end

if not empty(buffer) then
	local int = convert.toInt(buffer)
	resultArray[writePointer] = int
endif

 

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

Спасибо просто проблема, что я новичек в программировании 

в raw именно запятые идут с чередованием числа, с буффером пока работать ненаучился. 

За код спасибо попробую разобраться. 

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016
  while (Serial.available() == 0); // Функци¤ Serial.аvailable() проверяет, есть ли в COM порте доступные для чтения данные!
  int val = Serial.parseInt(); // Читаем строку целиком
  Serial.println(val); // Вывод в терминал
  File dataFile = SD.open(String(val,DEC)); // Открываем файл (Можно открыть только 1 файл за раз) 
  if (dataFile) {
  while (dataFile.available()) { // Проверяем что файл не пустой
  Serial.write(dataFile.read()); // выводим содержимое в сериал 
// помогите плиииииз(((
// dataFile.read() содержит значение 4550,4450, 600,1650, 550,1700, 600,1650, 550,550, 600,550, 550,550, 550,550, 600,550, 550,1700, 550,1700, 550,1650, 550,600, 550,550, 550,600, 550,550, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,600, 550,550, 550,550, 600,550, 550,1700, 550,550, 550,550, 600,550, 550,1700, 550,1650, 600,1650, 550,1700, 600
// как суда прикрутить считывание значения dataFile.read() в буфер
  }
// и как прикрутить содержимое буфера
  unsigned int irSignal[67] = {сюда}; // Тут вставляем raw код из datafile
  irsend.sendRaw(irSignal, 67, 38); 
  dataFile.close(); // Если все считалось нормально то закрываем документ для дальнейшей работы с другими доками
 }
}

перерыл кучу сайтов. В упор немогу понять как работать с буфером. Уже мозги кипят...

помогите плииз

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ок, вот ПРИМЕРНЫЙ код:

unsigned int digits[50] = {0}; // под 50 первых чисел в файле

unsigned int readFile(const char* fileName)
{
	File f = SD.open(fileName);
	if(!f)
		return 0;

	String buffer;
	byte writeIndex = 0;
	
	char ch;
	while(f.read(&ch,sizeof(ch)) > 0)
	{
		if(ch == ',')
		{
			if(buffer != '') // если в буфере накоплено число
			{
				// записываем его в массив и передвигаем указатель записи
				digits[writeIndex++] = buffer.toInt();
				buffer = "";
				
				// проверяем на выход за пределы массива
				if(writeIndex >= 50)
				{
					f.close();
					return writeIndex;
				}
			}
		} // ch == ','
		else
		if(ch >= '0' && ch <= '9')
			buffer += ch;
	} // while
	
	// если дочитали и ещё есть, куда писать - записываем
	if(buffer != '' && writeIndex < 49)
		digits[writeIndex++] = buffer.toInt();
	
	f.close();
	return writeIndex;
}

void setup()
{
	// пример использования
	unsigned int readedRecords = readFile("raw.txt");
	if(readedRecords > 0)
	{
		// прочитали readedRecords записей, делаем с ними, что надо, например,
		// проходим по циклу
		for(byte i=0;i<50;i++)
			Serial.println(digits[i]);
	}
}

Компилировать не стал, проверять не стал - разберётесь, если что не так, думаю. Я даже комментарии добавил, на всякий. Писал навскидку, так что as is.

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

DIYMan пишет:

Ок, вот ПРИМЕРНЫЙ код:

unsigned int digits[50] = {0}; // под 50 первых чисел в файле

unsigned int readFile(const char* fileName)
{
	File f = SD.open(fileName);
	if(!f)
		return 0;

	String buffer;
	byte writeIndex = 0;
	
	char ch;
	while(f.read(&ch,sizeof(ch)) > 0)
	{
		if(ch == ',')
		{
			if(buffer != '') // если в буфере накоплено число
			{
				// записываем его в массив и передвигаем указатель записи
				digits[writeIndex++] = buffer.toInt();
				buffer = "";
				
				// проверяем на выход за пределы массива
				if(writeIndex >= 50)
				{
					f.close();
					return writeIndex;
				}
			}
		} // ch == ','
		else
		if(ch >= '0' && ch <= '9')
			buffer += ch;
	} // while
	
	// если дочитали и ещё есть, куда писать - записываем
	if(buffer != '' && writeIndex < 49)
		digits[writeIndex++] = buffer.toInt();
	
	f.close();
	return writeIndex;
}

void setup()
{
	// пример использования
	unsigned int readedRecords = readFile("raw.txt");
	if(readedRecords > 0)
	{
		// прочитали readedRecords записей, делаем с ними, что надо, например,
		// проходим по циклу
		for(byte i=0;i<50;i++)
			Serial.println(digits[i]);
	}
}

Компилировать не стал, проверять не стал - разберётесь, если что не так, думаю. Я даже комментарии добавил, на всякий. Писал навскидку, так что as is.

Спасибо за головоломку. Буду завтра разбираться... голова уже кипит. Чувство, что я опять в школе которую закончил давным давно ((( но кажись идея гиблая... не програмист я, да и код опять побходит к пределам возможностей ардуино уже материться (Недостаточно памяти, программа может работать нестабильно.), а еще нужно прицепить bluetooth wifi да и батарейку еще с отслеживанием заряда. Задумываюсь попытаться вообще прикрутить pgmspace.h

nurlanovic
nurlanovic аватар
Offline
Зарегистрирован: 16.06.2016

Посмотри в сторону конечных автоматов. (конечные автоматы) На их принципе работают компиляторы/интерпретатор, у тебя задача, что-то в духе интерпретации.

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

nurlanovic пишет:

Посмотри в сторону конечных автоматов. (конечные автоматы) На их принципе работают компиляторы/интерпретатор, у тебя задача, что-то в духе интерпретации.

И чего там компилировать/интерпретировать, что мы сравниваем с компиляторами/интерпретаторами? Вычитать из текстового файла числа? Да, задача как раз для конечного автомата. Для конечного автомата, Карл!

По ходу, кто-то увидел красивое словосочетание в книжке (ну или только вчера прочитал главу и пропёрся). Поверьте, задача ТС не то, что тривиальная - она архитривиальная, и никакими конечными автоматами там и не пахнет. И пахнуть не должно.

nurlanovic
nurlanovic аватар
Offline
Зарегистрирован: 16.06.2016

Хорошо, вот псевдокод:

#include <stdlib.h> 
#include<vector.h>

#define WAIT_INPUT 0
#define EXPECT_COMMA 1
#define EXPECT_NUM 2

unsigned int state = WAIT_INPUT;

char* inputString; // входная строка с байтами
char tok; // символ
unsigned int i = 0;

std::Vector<int> out; // здесь будут лежать отпарсенные числа
std::Vector<char> ch; // здесь будут лежать принятые числа

int arr_size = size(inputString);

while (i < arr_size) {
tok = inputString[i];

switch (state) {
case WAIT_INPUT:
     if (tok >= '0' && tok <= '9') {
          ch.clear();
          state = EXPECT_NUM;
          continue;
     }
break;

case EXPECT_NUM:
     if (tok >= '0' && tok <= '9') {
          ch.push_back(tok);
     } else if (tok == ',' || i == arr_size-1) {
        state = EXPECT_COMMA;
        continue;
     }
break;

case EXPECT_COMMA:
     out.push_back(atoi(ch.data()));
     ch.clear();
     state = WAIT_INPUT;
break;
}

++i;

}

Это нестрогий парсер. Всё нормально подходит. Если снизу после ифов поставить проверку на неизвестные символы, будет строгий парсер. В чем я не прав?

AngelLeo
AngelLeo аватар
Offline
Зарегистрирован: 17.06.2016

Всем спасибо!проблема решена все работает...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

nurlanovic пишет:

 В чем я не прав?

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