Контроль передачи данных

Artur1985
Offline
Зарегистрирован: 19.02.2013

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

Структура проекта.
Компьютер, основная Mega (возможно Due, если ресурсов не хватит), вспомогательная Mega, дополнительная Mega.

Передача в обе стороны между Компьютером и основной Mega (Serial, UDP), основная с вспомогательной Mega (Serial). Дополнительная живет своей жизью.

Передача между компьютером и основной Mega, должна осуществляться как можно быстрее. В идеале, передача должна быть до 20 строк в секунду.

Формат данных
?NumberPacket(Номер пакета);XXX(Длина пакета);XXX(Тип операции);XXX(Параметр);XX(Тип данных);XXXXXXXXXX(Значение)!\n

Пока работа не закончена. Вот второй результат, в первом был delayMicroseconds(100), убрал по совету leshak.

Я любить, поэтому не судите строго.

/****************************** Переменные перечисления **********************************/
/// <summary>
/// Перечисление - Тип протокола передачи данных
/// </summary>
enum ConnectionTypeEnum
{
    /// <summary>
    /// Не выбран
    /// </summary>
    CT_None = 0,   
    /// <summary>
    /// Serial порт
    /// </summary>
    CT_Serial = 1,
    /// <summary>
    /// UDP
    /// </summary>	
    CT_UDP = 2
};

/// <summary>
/// Переменная определяющая тип связи с компьютером
/// </summary>
ConnectionTypeEnum connectionType = CT_Serial; 

/// <summary>
/// Перечисление - Тип операции 
/// </summary>
enum OperationTypeEnum     
{
    /// <summary>
    /// Не выбрана
    /// </summary>
    OT_None = 0,   
    /// <summary>
    /// Отправка данных с Arduino
    /// </summary>
    OT_SendDataFromArduino = 1,
    /// <summary>
    /// Отправка данных с PC
    /// </summary>
    OT_SendDataFromPC = 2,
    /// <summary>
    /// Получение данных с Arduino
    /// </summary>
    OT_ReciveDataFromArduino  = 3,
    /// <summary>
    /// Получение данных с PC
    /// </summary>
    OT_ReciveDataFromPC = 4,
    /// <summary> 
    /// Проверка вернувшихся данных с Arduino
    /// </summary>
    OT_CheckReturnFromArduino = 5,
    /// <summary>
    /// Проверка вернувшихся данных с PC
    /// </summary>
    OT_CheckReturnFromPC = 6,
    /// <summary>
    /// Старт ТПА
    /// </summary>
    OT_StartTPA = 7,
    /// <summary>
    /// Начало инициализации Arduino
    /// </summary>
    OT_InitArduinoBegin = 8,
    /// <summary>
    /// Инициализация Arduino
    /// </summary>
    OT_InitArduino = 9,
    /// <summary>
    /// Конец инициализации Arduino
    /// </summary>
    OT_InitArduinoFinish = 10,
    /// <summary>
    /// Начало настройки Arduino
    /// </summary>
    OT_SetupArduinoBegin = 11,
    /// <summary>
    /// Настройка Arduino
    /// </summary>
    OT_SetupArduino = 12,
    /// <summary>
    /// Конец настройки Arduino
    /// </summary>
    OT_SetupArduinoFinish = 13,
    /// <summary>
    /// Проверка соединения с Arduino
    /// </summary>
    OT_CheckConnectionFromArduino = 14,
    /// <summary>
    /// Проверка соединения с PC
    /// </summary>
    OT_CheckConnectionFromPC = 15,
	/// <summary>
	/// Команда ручного режима 
	/// </summary>
	OT_CommandManualMode = 16,
	/// <summary>
    /// Стоп ТПА
    /// </summary>
    OT_StopTPA = 17
};

/// <summary>
/// Переменная хранящая тип операции
/// </summary>
OperationTypeEnum operationType = OT_None; 

/// <summary>
/// Перечисление - Тип параметра
/// </summary>
enum ParametrEnum
{
    /// <summary>
    /// Не установлен
    /// </summary>
    P_None = 0
};

/// <summary>
/// Перечисление - Тип  данных параметра
/// </summary>
enum DataTypeEnum 
{
    /// <summary>
    /// Не указан
    /// </summary>
    DT_None = 0,
    /// <summary>
    /// Int
    /// </summary>
    DT_Int = 1
};
/******************************  /Переменные перечисления  **********************************/

/******************************  Переменные для работы с Serial портом  **********************************/
/// <summary>
/// Константа - Скорость Serial порта
/// </summary>
#define speedSerial 115200    
/******************************  /Переменные для работы с Serial портом **********************************/

/******************************  Переменные для работы передачи данных  **********************************/
/// <summary>
/// Константа - Символ новой строки
/// </summary>
#define newLine '\n'
/// <summary>
/// Константа - Символ начала пакета
/// </summary>
#define beginChar '?'
/// <summary>
/// Константа - Символ разделитель параметров пакета
/// </summary>
#define breakChar ';'
/// <summary>
/// Константа - Символ конца пакета
/// </summary>
#define endChar '!'
/// <summary>
/// Константа - Символ для очистки значения char
/// </summary>
#define clearChar '\0'

/// <summary>
/// Переменная хранящая завершено ли получения данных
/// </summary>
boolean finishReceiveData = false;

/// <summary>
/// Константа хранящая мак. размер массива хранящего пакет данных
/// </summary>
#define receiveSizeArrayCOM 38

/// <summary>
/// Переменная хранящее номер пакета в системе
/// </summary>
int globalNumberPacket = 0;

/// Объект String для хранения полученной строки
/// </summary>
String receiveData = "";

/// <summary>
/// Переменная хранящее номер символа начала пакета в пакете
/// </summary>
int indexBeginCharInPackage;
/// <summary>
/// Переменная хранящее номер символа конца пакета в пакете
/// </summary>
int indexEndCharInPackage;
/// <summary>
/// Переменная кол-во символов разделителя блоков данных в пакете
/// </summary>
int breakCharCountInPackage;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
String numberPacket;
/// <summary>
/// Переменная хранящее длину пакета
/// </summary>
String lenPacket; 
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
String operationTypePacket;
/// <summary>
/// Переменная хранящее тип параметра пакета
/// </summary>
String parametrPacket;
/// <summary>
/// Переменная хранящее тип данных параметра пакета
/// </summary>
String dataTypePacket;
/// <summary>
/// Переменная хранящее значение параметра пакета
/// </summary>
String valuePacket;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
int receiveNumberIntPacket = 0;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveLenIntPacket;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveOperationTypeIntPacket;

/// <summary>
/// Переменная хранящее реальную длину пакета, проверка после получения
/// </summary>
int receiveLength;
/******************************  /Переменные для работы передачи данных  **********************************/

/******************************  Переменные запуска ТПА  **********************************/
/// <summary>
/// Переменная хранящее состояние программы запущена или нет
/// </summary>
boolean beginWorkTPA = false; 

/// <summary>
/// Переменная хранящее состояние программы инициализирован ли ТПА
/// </summary>
boolean beginInitializationTPA = false;
/******************************  /Переменные запуска ТПА  **********************************/

/******************************  Переменные отладки  **********************************/
/// <summary>
/// Переменная хранящее время старта цикла, для проверки скорости выполнения цикла
/// </summary>
unsigned long timeCycleWork = 0;

#define IS_DEBUG true
/******************************  /Переменные отладки  **********************************/

/// <summary>
/// Настройка программы
/// </summary>
void setup ()
{
	// TODO: Добавить описание
	switch (connectionType) 
	{
		case CT_Serial:
			Serial.begin(speedSerial);
			break;
	}	

}

/// <summary>
/// Основной цикл
/// </summary>
void loop()
{   
	// Проверка времени обработки данных
	//timeCycleWork = millis();
	// /Проверка времени обработки данных

	// Выбираем протокол передачи данных
	switch (connectionType) 
	{
		case CT_Serial:
			// Протокол передачи данных на основе Serial порта

			// Получение данных с Serial порта
			GetReceiveDataFromSerial();
			break;
	}

	// Завершено ли получения данных
	if (finishReceiveData)
	{
		// Парсинг полученных данных
		ParseReceiveData();
	}
}

/******************************  Функции работы с Serial портом  **********************************/
/// <summary>
/// Получение данных с Serial порта
/// </summary>
void GetReceiveDataFromSerial()
{
	// TODO: Добавить описание 
	while(Serial.available())
	{
		/// <summary>
		/// Переменная хранящая последний полученный char
		/// </summary>
		char incomingChar = (char)Serial.read();

		if (incomingChar != newLine)
        {
            receiveData += incomingChar;
        }
		else
		{
			Serial.flush();

			finishReceiveData = true;
		}
	}
}

/// <summary>
/// Отправка данных по Serial порту
/// </summary>
void SendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	/*if (globalNumberPacket > 500)
	{
		Serial.println("Errore before");
	}
	globalNumberPacket++;
	if (globalNumberPacket > 500)
	{
		Serial.println("Errore after");
	}*/
	RepeatSendDataFromSerial(SendValue, OperationType, Parametr, DataType);          
}

/// <summary>
/// TODO: Добавить описание 
/// </summary>
void SendConfirmationDataFromSerial(String SendValue, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	RepeatSendDataFromSerial(SendValue, OT_CheckReturnFromArduino, Parametr, DataType); 
	ClearReceiveDataVariable();
}

/// <summary>
/// Повтор отправки данных по Serial порту
/// </summary>
void RepeatSendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	int sendValueLen = String(globalNumberPacket).length() +  String(OperationType).length() + String(Parametr).length() + String(DataType).length() + SendValue.length() + 7;
	sendValueLen += String(sendValueLen).length();
                  
	String sendPacket = beginChar + String(globalNumberPacket) + breakChar + String(sendValueLen) + breakChar + OperationType + breakChar + Parametr + breakChar + DataType + breakChar + SendValue + endChar + "\n";     
                                    
	Serial.print(sendPacket);
}
/******************************  /Функции работы с Serial портом  **********************************/

/******************************  Функции работы с полученными данными  **********************************/
/// <summary>
/// Очистка переменных получения данных, после получения данный
/// </summary>
void ClearReceiveDataVariable()
{
	// TODO: Добавить описание 
	indexBeginCharInPackage = indexEndCharInPackage = breakCharCountInPackage = receiveLenIntPacket = receiveLength = receiveOperationTypeIntPacket = 0;
	receiveData = numberPacket = lenPacket = operationTypePacket = parametrPacket = dataTypePacket = valuePacket = "";
		
	finishReceiveData = false;
}

/// <summary>
/// Парсинг полученных данных
/// </summary>
void ParseReceiveData()
{
	// Получаем длину пакета
	receiveLength = receiveData.length();

	// Пробегаемся по массиву хранящий пакет данных
	for (int i = 0; i < receiveLength; i++)
	{
		char receiveDataCurrentChar = receiveData.charAt(i);
		switch (receiveDataCurrentChar) {
			case beginChar:
				// Получаем индекс символ начала пакета в пакете
				indexBeginCharInPackage = i;
				break;
			case endChar:
				// Получаем индекс символ конца пакета в пакете
				indexEndCharInPackage = i;
				break;
			case breakChar:
				// Получаем кол-во символов разделителя блоков данных в пакете
				breakCharCountInPackage++;
				break;
			default:
				// В зависимости от номера блока данных в пакете, заполняем переменные блоков
				switch (breakCharCountInPackage) {
					case 0:
						// Номер пакета в системе
						numberPacket += receiveDataCurrentChar;
						break;
					case 1:
						// Длина пакета
						lenPacket += receiveDataCurrentChar;
						break;
					case 2:
						// Тип операции пакета
						operationTypePacket += receiveDataCurrentChar;
						break;
					case 3:
						// Тип операции пакета
						parametrPacket += receiveDataCurrentChar;
						break;
					case 4:
						// Тип данных параметра пакета
						dataTypePacket += receiveDataCurrentChar;
						break;
					case 5:
						// Значение параметра пакета
						valuePacket += receiveDataCurrentChar;				
						break;
				} 
				break;
		}
	}

	if (breakCharCountInPackage != 5)
	{
		ErroreDataReceived("1",1);

		return;
	}

	// Номер пакета в системе, Int
	receiveNumberIntPacket = numberPacket.toInt();

	// Номер пакета в системе, Int
	receiveLenIntPacket = lenPacket.toInt();

	// Тип операции пакета, Int
	receiveOperationTypeIntPacket = operationTypePacket.toInt();

	Serial.println(receiveData);

	// Проверка корректности полученного пакета 
	if (indexBeginCharInPackage == 0 && breakCharCountInPackage == 5	// Индекс символа начала пакета, должен быть равен 0, кол-во блоков данных должно быть 5	
			&& indexEndCharInPackage == (receiveLength - 1)				// Индекс символа конца пакета, должен быть равен значению блока длины пакета - 1
			&& receiveLenIntPacket == receiveLength)					// Реальная длина пакета должна быть равна значению блока длины пакета
			
	{
		// Определяем тип операции пакета
		switch(receiveOperationTypeIntPacket)
		{
			case OT_StartTPA:
				// Старт ТПА

				SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());

				// Устанавливаем состояние программы запущена
				beginWorkTPA = true;
				break;	
			default:
				int globalNumberPacketAndOne = globalNumberPacket;
				if (receiveOperationTypeIntPacket != OT_CheckReturnFromPC && receiveNumberIntPacket == globalNumberPacketAndOne)
				{			
					SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());
				}
				else 
				{
					if (receiveNumberIntPacket == globalNumberPacketAndOne)
					{
						switch(receiveOperationTypeIntPacket)
						{
							case OT_StopTPA:
								// Стоп ТПА
							
								SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());

								// Устанавливаем состояние программы остановлена
								beginWorkTPA = false;
								break;
						}
					}
					else 
					{
						ErroreDataReceived("2",2);
					}
				}		
				break;
		}
	}
	else 
	{
		ErroreDataReceived("3",3);
	}
}
/******************************  /Функции работы с полученными данными  **********************************/

/******************************  Функции работы с ошибками  **********************************/
/// <summary>
/// Ошибка получения данных
/// </summary>
void ErroreDataReceived(String DataReceived, int TypeErrore)
{
	// TODO: Добавить описание 
	ClearReceiveDataVariable();

	Errore(DataReceived, 0);
}

/// <summary>
/// Ошибка получения данных
/// </summary>
void Errore(String Data, int TypeErrore)
{
	// TODO: Добавить описание 
	//FullStopTPA();

	Log(Data, TypeErrore, true);
}
/******************************  /Функции работы с ошибками  **********************************/

/******************************  Функции работы с логом  **********************************/
/// <summary>
/// Логирование
/// </summary>
void Log(String Data, int TypeLog, bool isErrore)
{
	// TODO: Добавить описание 
	switch (connectionType) 
	{
		case CT_Serial:
			Serial.println(Data);
			break;
	}
}
/******************************  /Функции работы с логом  **********************************/

Работа, еще не закончена. Осталось побороть 1 ошибку, сделать контроль номера пакета, оптимизировать и нормально закомментировать.

Ошибка, даже не в ардуине, а в принимающей программе на C#. Получаю, странные символы перед ответом
����. Если пользоваться монитором Сом порта ардуины, то все норм.

Вот настройки соединения порта в программе. 
 

            ArduinoSerialPort.PortName = "COM25";
            ArduinoSerialPort.BaudRate = 115200;

            ArduinoSerialPort.Parity = Parity.None;
            ArduinoSerialPort.DataBits = 8;
            ArduinoSerialPort.StopBits = StopBits.One;

            //ArduinoSerialPort.ReadTimeout = 500;
            //ArduinoSerialPort.WriteTimeout = 500;
            ArduinoSerialPort.Encoding = Encoding.UTF8;

            ArduinoSerialPort.NewLine = "\n";

            ArduinoSerialPort.DataReceived += new SerialDataReceivedEventHandler(ArduinoSerialPort_DataReceived);

            ArduinoSerialPort.Open();

Может кто-то сталкивался с такой проблемой.

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

 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Забыл, строка для проверки 

?0;14;7;0;1;1!

Artur1985
Offline
Зарегистрирован: 19.02.2013

Вернул версию с delayMicroseconds(100), работает без ошибки.
До 35 запросов в 1с. с возвратом посылаемому устройству. И отображение в программе. 
 

Думаю, можно и больше, но надо оптимизировать код.

 

/******************************  Переменные перечисления  **********************************/
/// <summary>
/// Перечисление - Тип протокола передачи данных
/// </summary>
enum ConnectionTypeEnum
{
    /// <summary>
    /// Не выбран
    /// </summary>
    CT_None = 0,   
    /// <summary>
    /// Serial порт
    /// </summary>
    CT_Serial = 1,
    /// <summary>
    /// UDP
    /// </summary>	
    CT_UDP = 2
};

/// <summary>
/// Переменная определяющая тип связи с компьютером
/// </summary>
ConnectionTypeEnum connectionType = CT_Serial; 

/// <summary>
/// Перечисление - Тип операции 
/// </summary>
enum OperationTypeEnum     
{
    /// <summary>
    /// Не выбрана
    /// </summary>
    OT_None = 0,   
    /// <summary>
    /// Отправка данных с Arduino
    /// </summary>
    OT_SendDataFromArduino = 1,
    /// <summary>
    /// Отправка данных с PC
    /// </summary>
    OT_SendDataFromPC = 2,
    /// <summary>
    /// Получение данных с Arduino
    /// </summary>
    OT_ReciveDataFromArduino  = 3,
    /// <summary>
    /// Получение данных с PC
    /// </summary>
    OT_ReciveDataFromPC = 4,
    /// <summary> 
    /// Проверка вернувшихся данных с Arduino
    /// </summary>
    OT_CheckReturnFromArduino = 5,
    /// <summary>
    /// Проверка вернувшихся данных с PC
    /// </summary>
    OT_CheckReturnFromPC = 6,
    /// <summary>
    /// Старт ТПА
    /// </summary>
    OT_StartTPA = 7,
    /// <summary>
    /// Начало инициализации Arduino
    /// </summary>
    OT_InitArduinoBegin = 8,
    /// <summary>
    /// Инициализация Arduino
    /// </summary>
    OT_InitArduino = 9,
    /// <summary>
    /// Конец инициализации Arduino
    /// </summary>
    OT_InitArduinoFinish = 10,
    /// <summary>
    /// Начало настройки Arduino
    /// </summary>
    OT_SetupArduinoBegin = 11,
    /// <summary>
    /// Настройка Arduino
    /// </summary>
    OT_SetupArduino = 12,
    /// <summary>
    /// Конец настройки Arduino
    /// </summary>
    OT_SetupArduinoFinish = 13,
    /// <summary>
    /// Проверка соединения с Arduino
    /// </summary>
    OT_CheckConnectionFromArduino = 14,
    /// <summary>
    /// Проверка соединения с PC
    /// </summary>
    OT_CheckConnectionFromPC = 15,
	/// <summary>
	/// Команда ручного режима 
	/// </summary>
	OT_CommandManualMode = 16,
	/// <summary>
    /// Стоп ТПА
    /// </summary>
    OT_StopTPA = 17
};

/// <summary>
/// Переменная хранящая тип операции
/// </summary>
OperationTypeEnum operationType = OT_None; 

/// <summary>
/// Перечисление - Тип параметра
/// </summary>
enum ParametrEnum
{
    /// <summary>
    /// Не установлен
    /// </summary>
    P_None = 0
};

/// <summary>
/// Перечисление - Тип  данных параметра
/// </summary>
enum DataTypeEnum 
{
    /// <summary>
    /// Не указан
    /// </summary>
    DT_None = 0,
    /// <summary>
    /// Int
    /// </summary>
    DT_Int = 1
};
/******************************  /Переменные перечисления  **********************************/

/******************************  Переменные для работы с Serial портом  **********************************/
/// <summary>
/// Константа - Скорость Serial порта
/// </summary>
#define speedSerial 115200    
/******************************  /Переменные для работы с Serial портом **********************************/

/******************************  Переменные для работы передачи данных  **********************************/
/// <summary>
/// Константа - Символ новой строки
/// </summary>
#define newLine '\n'
/// <summary>
/// Константа - Символ начала пакета
/// </summary>
#define beginChar '?'
/// <summary>
/// Константа - Символ разделитель параметров пакета
/// </summary>
#define breakChar ';'
/// <summary>
/// Константа - Символ конца пакета
/// </summary>
#define endChar '!'
/// <summary>
/// Константа - Символ для очистки значения char
/// </summary>
#define clearChar '\0'

/// <summary>
/// Переменная хранящая последний полученный char
/// </summary>
char incomingChar;

/// <summary>
/// Переменная хранящая индекс текущего char в массиве хранящего пакет данных
/// </summary>
int indexCharInArray;

/// <summary>
/// Переменная хранящая завершено ли получения данных
/// </summary>
boolean finishReceiveData = false;

/// <summary>
/// Константа хранящая мак. размер массива хранящего пакет данных
/// </summary>
#define receiveSizeArrayCOM 40
/// <summary>
/// Массив хранящий пакет данных
/// </summary>
char receiveCharArrayCOM[receiveSizeArrayCOM];

/// <summary>
/// Переменная хранящее номер пакета в системе
/// </summary>
int globalNumberPacket = 0;

/// <summary>
/// Переменная хранящее номер символа начала пакета в пакете
/// </summary>
int indexBeginCharInPackage;
/// <summary>
/// Переменная хранящее номер символа конца пакета в пакете
/// </summary>
int indexEndCharInPackage;
/// <summary>
/// Переменная кол-во символов разделителя блоков данных в пакете
/// </summary>
int breakCharCountInPackage;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
String numberPacket;
/// <summary>
/// Переменная хранящее длину пакета
/// </summary>
String lenPacket; 
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
String operationTypePacket;
/// <summary>
/// Переменная хранящее тип параметра пакета
/// </summary>
String parametrPacket;
/// <summary>
/// Переменная хранящее тип данных параметра пакета
/// </summary>
String dataTypePacket;
/// <summary>
/// Переменная хранящее значение параметра пакета
/// </summary>
String valuePacket;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
int receiveNumberIntPacket = 0;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveLenIntPacket;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveOperationTypeIntPacket;

/// <summary>
/// Переменная хранящее реальную длину пакета, проверка после получения
/// </summary>
int receiveLength;
/******************************  /Переменные для работы передачи данных  **********************************/

/******************************  Переменные запуска ТПА  **********************************/
/// <summary>
/// Переменная хранящее состояние программы запущена или нет
/// </summary>
boolean beginWorkTPA = false; 

/// <summary>
/// Переменная хранящее состояние программы инициализирован ли ТПА
/// </summary>
boolean beginInitializationTPA = false;
/******************************  /Переменные запуска ТПА  **********************************/

/******************************  Переменные отладки  **********************************/
/// <summary>
/// Переменная хранящее время старта цикла, для проверки скорости выполнения цикла
/// </summary>
unsigned long timeCycleWork = 0;

#define IS_DEBUG true
/******************************  /Переменные отладки  **********************************/

/// <summary>
/// Настройка программы
/// </summary>
void setup ()
{
	// TODO: Добавить описание
	switch (connectionType) 
	{
		case CT_Serial:
			Serial.begin(speedSerial);
			break;
	}	
}

/// <summary>
/// Основной цикл
/// </summary>
void loop()
{   
	// Проверка времени обработки данных
	//timeCycleWork = millis();
	// /Проверка времени обработки данных

	// Очистка переменных получения данных, после получения данных
	ClearReceiveDataVariable();

	// Запущена или программа ТПА
	if (!beginWorkTPA)
	{
		// Программа ТПА не запущена

		// Выбираем протокол передачи данных
		switch (connectionType) 
		{
			case CT_Serial:
				// Протокол передачи данных на основе Serial порта

				// Получение данных с Serial порта
				GetReceiveDataFromSerial();
				break;
		}	

		// Парсинг полученных данных
		ParseReceiveData();

		// Обрываем выполнение loop
		return;
	}
 
	// Состояние программы инициализирован ли ТПА
	if (!beginInitializationTPA)
	{	
		// ТПА не инициализирован
	
		// Устанавливаем состояние программы инициализирован
		beginInitializationTPA = true;
	}

	// Выбираем протокол передачи данных
	switch (connectionType) 
	{
		case CT_Serial:
			// Протокол передачи данных на основе Serial порта

			// Получение данных с Serial порта
			GetReceiveDataFromSerial();
			break;
	}	
    
	// Парсинг полученных данных
	ParseReceiveData();

	delay(25);
	SendDataFromSerial("Hello", OT_SendDataFromArduino, P_None, DT_Int);	        

	// Проверка времени обработки данных
	//unsigned long workTime = millis() - timeCycleWork;
	//Serial.println(workTime);
	// /Проверка времени обработки данных
}

/******************************  Функции работы с Serial портом  **********************************/
/// <summary>
/// Получение данных с Serial порта
/// </summary>
void GetReceiveDataFromSerial()
{
	// TODO: Добавить описание 
	while(Serial.available())
	{
		incomingChar = (char)Serial.read();
		if(incomingChar != newLine)
		{
			receiveCharArrayCOM[indexCharInArray++] = incomingChar;
		}
		else
		{
			finishReceiveData = true;
		}
	  
		delayMicroseconds(100); 
	}
}

/// <summary>
/// Отправка данных по Serial порту
/// </summary>
void SendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	RepeatSendDataFromSerial(SendValue, OperationType, Parametr, DataType);          
}

/// <summary>
/// TODO: Добавить описание 
/// </summary>
void SendConfirmationDataFromSerial(String SendValue, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	RepeatSendDataFromSerial(SendValue, OT_CheckReturnFromArduino, Parametr, DataType);          
}

/// <summary>
/// Повтор отправки данных по Serial порту
/// </summary>
void RepeatSendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	int sendValueLen = String(globalNumberPacket).length() +  String(OperationType).length() + String(Parametr).length() + String(DataType).length() + SendValue.length() + 7;
	sendValueLen += String(sendValueLen).length();
                  
	String sendPacket = beginChar + String(globalNumberPacket) + breakChar + String(sendValueLen) + breakChar + OperationType + breakChar + Parametr + breakChar + DataType + breakChar + SendValue + endChar;     
                                    
	SerialPrintLine(sendPacket);
}

void SerialPrintLine(String SendValue)
{
	Serial.print(SendValue);
	Serial.print(newLine);
}
/******************************  /Функции работы с Serial портом  **********************************/

/******************************  Функции работы с полученными данными  **********************************/
/// <summary>
/// Очистка переменных получения данных, после получения данный
/// </summary>
void ClearReceiveDataVariable()
{
	// TODO: Добавить описание 
	indexCharInArray = 0;
	memset(receiveCharArrayCOM,clearChar,receiveSizeArrayCOM); 

	indexBeginCharInPackage = indexEndCharInPackage = breakCharCountInPackage = receiveLenIntPacket = receiveLength = receiveOperationTypeIntPacket = 0;
	numberPacket = lenPacket = operationTypePacket = parametrPacket = dataTypePacket = valuePacket = "";
		
	finishReceiveData = false;
}

/// <summary>
/// Парсинг полученных данных
/// </summary>
void ParseReceiveData()
{
	// Завершено ли получения данных
	if (finishReceiveData)
	{
		// Получаем длину пакета
		receiveLength = strlen(receiveCharArrayCOM);
		
		// Пробегаемся по массиву хранящий пакет данных
		for (int i = 0; i < receiveLength; i++)
		{
			switch (receiveCharArrayCOM[i]) {
				case beginChar:
					// Получаем индекс символ начала пакета в пакете
					indexBeginCharInPackage = i;
					break;
				case endChar:
					// Получаем индекс символ конца пакета в пакете
					indexEndCharInPackage = i;
					break;
				case breakChar:
					// Получаем кол-во символов разделителя блоков данных в пакете
					breakCharCountInPackage++;
					break;
				default:
					// В зависимости от номера блока данных в пакете, заполняем переменные блоков
					switch (breakCharCountInPackage) {
						case 0:
							// Номер пакета в системе
							numberPacket += receiveCharArrayCOM[i];
							break;
						case 1:
							// Длина пакета
							lenPacket += receiveCharArrayCOM[i];
							break;
						case 2:
							// Тип операции пакета
							operationTypePacket += receiveCharArrayCOM[i];
							break;
						case 3:
							// Тип операции пакета
							parametrPacket += receiveCharArrayCOM[i];
							break;
						case 4:
							// Тип данных параметра пакета
							dataTypePacket += receiveCharArrayCOM[i];
							break;
						case 5:
							// Значение параметра пакета
							valuePacket += receiveCharArrayCOM[i];					
							break;
					} 
					break;
			}
		}
       
		if (breakCharCountInPackage != 5)
		{
			ErroreDataReceived("1",1);

			return;
		}
		
		// Номер пакета в системе, Int
		receiveNumberIntPacket = numberPacket.toInt();

		// Номер пакета в системе, Int
		receiveLenIntPacket = lenPacket.toInt();

		// Тип операции пакета, Int
		receiveOperationTypeIntPacket = operationTypePacket.toInt();

		// Проверка корректности полученного пакета 
		if (indexBeginCharInPackage == 0 && breakCharCountInPackage == 5	// Индекс символа начала пакета, должен быть равен 0, кол-во блоков данных должно быть 5	
				&& indexEndCharInPackage == (receiveLength - 1)				// Индекс символа конца пакета, должен быть равен значению блока длины пакета - 1
				&& receiveLenIntPacket == receiveLength						// Реальная длина пакета должна быть равна значению блока длины пакета
				)
		{
			// Определяем тип операции пакета
			switch(receiveOperationTypeIntPacket)
			{
				case OT_StartTPA:
					// Старт ТПА

					SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());

					// Устанавливаем состояние программы запущена
					beginWorkTPA = true;
					break;	
				default:
					int globalNumberPacketAndOne = globalNumberPacket;//globalNumberPacket + 1;
					if (receiveOperationTypeIntPacket != OT_CheckReturnFromPC && receiveNumberIntPacket == globalNumberPacketAndOne)
					{			
						SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());
					}
					else 
					{
						if (receiveNumberIntPacket == globalNumberPacketAndOne)
						{
							switch(receiveOperationTypeIntPacket)
							{
								case OT_StopTPA:
									// Стоп ТПА
							
									SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());
								
									//globalNumberPacket = 0;

									// Устанавливаем состояние программы остановлена
									beginWorkTPA = false;
									break;
							}
						}
						else 
						{
							ErroreDataReceived("2",0);
						}
					}		
					break;
			}
		}
		else 
		{
			ErroreDataReceived("3",0);
		}              								
	}
}
/******************************  /Функции работы с полученными данными  **********************************/

/******************************  Функции работы с ошибками  **********************************/
/// <summary>
/// Ошибка получения данных
/// </summary>
void ErroreDataReceived(String DataReceived, int TypeErrore)
{
	// TODO: Добавить описание 
	Errore(DataReceived, 0);
}

/// <summary>
/// Ошибка получения данных
/// </summary>
void Errore(String Data, int TypeErrore)
{
	// TODO: Добавить описание 
	//FullStopTPA();

	Log(Data, TypeErrore, true);
}
/******************************  /Функции работы с ошибками  **********************************/

/******************************  Функции работы с логом  **********************************/
/// <summary>
/// Логирование
/// </summary>
void Log(String Data, int TypeLog, bool isErrore)
{
	// TODO: Добавить описание 
	switch (connectionType) 
	{
		case CT_Serial:
			SerialPrintLine(Data);
			break;
	}
}
/******************************  /Функции работы с логом  **********************************/

Пока, протестирую и дополню номером пакет.

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

Сильно не вникал.... но не вижу нескольких нужных вещей:

1. Игнорирование символа \r  (Вы вкурсе что Serial.println() шлет в конце строки \r\n?)
2. При обнаружении конца строки, в массив receiveCharArrayCOM нигде не записывается ноль. Все сишные функции работы со строками предполагают \0 в качестве символа конца строки). Без этого, все будет работать "как повезет".
3. Не видно проверок выхода за границы массива receiveCharArrayCOM . А вдруг прилезет строка длинней чем вы выделили память под буффер? Кстати не забудте, что принять мы можем не больше чем "размер буфера - 1". Так как под нулевой символ должен быть всегда.

 

 

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

Погодите, похоже что вы делаете

ClearReceiveDataVariable()

в начале каждого loop().

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

 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Большое спасибо, за замечания.

leshak пишет:

1. Игнорирование символа \r  (Вы вкурсе что Serial.println() шлет в конце строки \r\n?)

Во втором варианте, у меня нет Serial.println(). Но узнал, не давно, поэтому в 1 варианте без delay есть.

 

void SerialPrintLine(String SendValue)
{
    Serial.print(SendValue);
    Serial.print(newLine);
}

 

leshak пишет:

2. При обнаружении конца строки, в массив receiveCharArrayCOM нигде не записывается ноль. Все сишные функции работы со строками предполагают \0 в качестве символа конца строки). Без этого, все будет работать "как повезет".

Не знал.

leshak пишет:

3. Не видно проверок выхода за границы массива receiveCharArrayCOM . А вдруг прилезет строка длинней чем вы выделили память под буффер? Кстати не забудте, что принять мы можем не больше чем "размер буфера - 1". Так как под нулевой символ должен быть всегда.

Да упустил из виду.

leshak пишет:

Погодите, похоже что вы делаете

ClearReceiveDataVariable()

в начале каждого loop().

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


Да, во втором варианте, это есть.

Сейчас попробую в 1 вариант, без delay перенести, наработки второй версии и то, что Вы отметили.
Большое спасибо. 
 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Переделал код
 

/****************************** Переменные перечисления **********************************/
/// <summary>
/// Перечисление - Тип протокола передачи данных
/// </summary>
enum ConnectionTypeEnum
{
    /// <summary>
    /// Не выбран
    /// </summary>
    CT_None = 0,   
    /// <summary>
    /// Serial порт
    /// </summary>
    CT_Serial = 1,
    /// <summary>
    /// UDP
    /// </summary>	
    CT_UDP = 2
};

/// <summary>
/// Переменная определяющая тип связи с компьютером
/// </summary>
ConnectionTypeEnum connectionType = CT_Serial; 

/// <summary>
/// Перечисление - Тип операции 
/// </summary>
enum OperationTypeEnum     
{
    /// <summary>
    /// Не выбрана
    /// </summary>
    OT_None = 0,   
    /// <summary>
    /// Отправка данных с Arduino
    /// </summary>
    OT_SendDataFromArduino = 1,
    /// <summary>
    /// Отправка данных с PC
    /// </summary>
    OT_SendDataFromPC = 2,
    /// <summary>
    /// Получение данных с Arduino
    /// </summary>
    OT_ReciveDataFromArduino  = 3,
    /// <summary>
    /// Получение данных с PC
    /// </summary>
    OT_ReciveDataFromPC = 4,
    /// <summary> 
    /// Проверка вернувшихся данных с Arduino
    /// </summary>
    OT_CheckReturnFromArduino = 5,
    /// <summary>
    /// Проверка вернувшихся данных с PC
    /// </summary>
    OT_CheckReturnFromPC = 6,
    /// <summary>
    /// Старт ТПА
    /// </summary>
    OT_StartTPA = 7,
    /// <summary>
    /// Начало инициализации Arduino
    /// </summary>
    OT_InitArduinoBegin = 8,
    /// <summary>
    /// Инициализация Arduino
    /// </summary>
    OT_InitArduino = 9,
    /// <summary>
    /// Конец инициализации Arduino
    /// </summary>
    OT_InitArduinoFinish = 10,
    /// <summary>
    /// Начало настройки Arduino
    /// </summary>
    OT_SetupArduinoBegin = 11,
    /// <summary>
    /// Настройка Arduino
    /// </summary>
    OT_SetupArduino = 12,
    /// <summary>
    /// Конец настройки Arduino
    /// </summary>
    OT_SetupArduinoFinish = 13,
    /// <summary>
    /// Проверка соединения с Arduino
    /// </summary>
    OT_CheckConnectionFromArduino = 14,
    /// <summary>
    /// Проверка соединения с PC
    /// </summary>
    OT_CheckConnectionFromPC = 15,
	/// <summary>
	/// Команда ручного режима 
	/// </summary>
	OT_CommandManualMode = 16,
	/// <summary>
    /// Стоп ТПА
    /// </summary>
    OT_StopTPA = 17
};

/// <summary>
/// Переменная хранящая тип операции
/// </summary>
OperationTypeEnum operationType = OT_None; 

/// <summary>
/// Перечисление - Тип параметра
/// </summary>
enum ParametrEnum
{
    /// <summary>
    /// Не установлен
    /// </summary>
    P_None = 0
};

/// <summary>
/// Перечисление - Тип  данных параметра
/// </summary>
enum DataTypeEnum 
{
    /// <summary>
    /// Не указан
    /// </summary>
    DT_None = 0,
    /// <summary>
    /// Int
    /// </summary>
    DT_Int = 1
};
/******************************  /Переменные перечисления  **********************************/

/******************************  Переменные для работы с Serial портом  **********************************/
/// <summary>
/// Константа - Скорость Serial порта
/// </summary>
#define speedSerial 115200    
/******************************  /Переменные для работы с Serial портом **********************************/

/******************************  Переменные для работы передачи данных  **********************************/
/// <summary>
/// Константа - Символ новой строки
/// </summary>
#define newLine '\n'

/// <summary>
/// Константа - Символ начала пакета
/// </summary>
#define beginChar '?'
/// <summary>
/// Константа - Символ разделитель параметров пакета
/// </summary>
#define breakChar ';'
/// <summary>
/// Константа - Символ конца пакета
/// </summary>
#define endChar '!'
/// <summary>
/// Константа - Символ для очистки значения char
/// </summary>
#define clearChar '\0'

/// <summary>
/// Переменная хранящая завершено ли получения данных
/// </summary>
boolean finishReceiveData = false;

/// <summary>
/// Переменная хранящее номер пакета в системе
/// </summary>
int globalNumberPacket = 0;

/// <summary>
/// Переменная хранящая индекс текущего char в массиве хранящего пакет данных
/// </summary>
int indexCharInArray;

/// <summary>
/// Константа хранящая мак. размер массива хранящего пакет данных
/// </summary>
#define receiveSizeArrayCOM 40
/// <summary>
/// Массив хранящий пакет данных
/// </summary>
char receiveCharArrayCOM[receiveSizeArrayCOM];

/// <summary>
/// Переменная хранящее номер символа начала пакета в пакете
/// </summary>
int indexBeginCharInPackage;
/// <summary>
/// Переменная хранящее номер символа конца пакета в пакете
/// </summary>
int indexEndCharInPackage;
/// <summary>
/// Переменная кол-во символов разделителя блоков данных в пакете
/// </summary>
int breakCharCountInPackage;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
String numberPacket;
/// <summary>
/// Переменная хранящее длину пакета
/// </summary>
String lenPacket; 
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
String operationTypePacket;
/// <summary>
/// Переменная хранящее тип параметра пакета
/// </summary>
String parametrPacket;
/// <summary>
/// Переменная хранящее тип данных параметра пакета
/// </summary>
String dataTypePacket;
/// <summary>
/// Переменная хранящее значение параметра пакета
/// </summary>
String valuePacket;

/// <summary>
/// Переменная хранящее номер пакета
/// </summary>
int receiveNumberIntPacket = 0;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveLenIntPacket;
/// <summary>
/// Переменная хранящее тип операции пакета
/// </summary>
int receiveOperationTypeIntPacket;

/// <summary>
/// Переменная хранящее реальную длину пакета, проверка после получения
/// </summary>
int receiveLength;
/******************************  /Переменные для работы передачи данных  **********************************/

/******************************  Переменные запуска ТПА  **********************************/
/// <summary>
/// Переменная хранящее состояние программы запущена или нет
/// </summary>
boolean beginWorkTPA = false; 

/// <summary>
/// Переменная хранящее состояние программы инициализирован ли ТПА
/// </summary>
boolean beginInitializationTPA = false;
/******************************  /Переменные запуска ТПА  **********************************/

/******************************  Переменные отладки  **********************************/
/// <summary>
/// Переменная хранящее время старта цикла, для проверки скорости выполнения цикла
/// </summary>
unsigned long timeCycleWork = 0;

#define IS_DEBUG true
/******************************  /Переменные отладки  **********************************/

/// <summary>
/// Настройка программы
/// </summary>
void setup ()
{
	// TODO: Добавить описание
	switch (connectionType) 
	{
		case CT_Serial:
			Serial.begin(speedSerial);
			break;
	}	

}

/// <summary>
/// Основной цикл
/// </summary>
void loop()
{   
	// Проверка времени обработки данных
	//timeCycleWork = millis();
	// /Проверка времени обработки данных

	// Выбираем протокол передачи данных
	switch (connectionType) 
	{
		case CT_Serial:
			// Протокол передачи данных на основе Serial порта

			// Получение данных с Serial порта
			GetReceiveDataFromSerial();
			break;
	}

	// Завершено ли получения данных
	if (finishReceiveData)
	{
		// Парсинг полученных данных
		ParseReceiveData();

		ClearReceiveDataVariable();
	}

	// Проверка времени обработки данных
	//unsigned long workTime = millis() - timeCycleWork;
	//SerialPrintLine(workTime);
	// /Проверка времени обработки данных
}

/******************************  Функции работы с Serial портом  **********************************/
/// <summary>
/// Получение данных с Serial порта
/// </summary>
void GetReceiveDataFromSerial()
{
	// TODO: Добавить описание 
	while(Serial.available())
	{
		/// <summary>
		/// Переменная хранящая последний полученный char
		/// </summary>
		char incomingChar = (char)Serial.read();

		if(incomingChar != newLine &&
			incomingChar != clearChar)
		{
			receiveCharArrayCOM[indexCharInArray] = incomingChar;
			indexCharInArray++;
		}
		else
		{
			receiveCharArrayCOM[indexCharInArray] = '\0';

			finishReceiveData = true;
		}
	}
}

/// <summary>
/// Отправка данных по Serial порту
/// </summary>
void SendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	RepeatSendDataFromSerial(SendValue, OperationType, Parametr, DataType);          
}

/// <summary>
/// TODO: Добавить описание 
/// </summary>
void SendConfirmationDataFromSerial(String SendValue, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	RepeatSendDataFromSerial(SendValue, OT_CheckReturnFromArduino, Parametr, DataType); 
	ClearReceiveDataVariable();
}

/// <summary>
/// Повтор отправки данных по Serial порту
/// </summary>
void RepeatSendDataFromSerial(String SendValue, int OperationType, int Parametr, int DataType)
{
	// TODO: Добавить описание 
	int sendValueLen = String(globalNumberPacket).length() +  String(OperationType).length() + String(Parametr).length() + String(DataType).length() + SendValue.length() + 7;
	sendValueLen += String(sendValueLen).length();
                  
	String sendPacket = beginChar + String(globalNumberPacket) + breakChar + String(sendValueLen) + breakChar + OperationType + breakChar + Parametr + breakChar + DataType + breakChar + SendValue + endChar;     
                                    
	SerialPrintLine(sendPacket);
}

void SerialPrintLine(String SendValue)
{
	SendValue += newLine;
	Serial.print(SendValue);
}
/******************************  /Функции работы с Serial портом  **********************************/

/******************************  Функции работы с полученными данными  **********************************/
/// <summary>
/// Очистка переменных получения данных, после получения данный
/// </summary>
void ClearReceiveDataVariable()
{
	// TODO: Добавить описание 
	indexCharInArray = 0;
	memset(receiveCharArrayCOM,clearChar,receiveSizeArrayCOM); 

	indexBeginCharInPackage = indexEndCharInPackage = breakCharCountInPackage = receiveLenIntPacket = receiveLength = receiveOperationTypeIntPacket = 0;
	numberPacket = lenPacket = operationTypePacket = parametrPacket = dataTypePacket = valuePacket = "";
		
	finishReceiveData = false;
}

/// <summary>
/// Парсинг полученных данных
/// </summary>
void ParseReceiveData()
{
	// Завершено ли получения данных
	if (finishReceiveData)
	{
		// Получаем длину пакета
		receiveLength = strlen(receiveCharArrayCOM);
		
		// Пробегаемся по массиву хранящий пакет данных
		for (int i = 0; i < receiveLength; i++)
		{
			switch (receiveCharArrayCOM[i]) {
				case beginChar:
					// Получаем индекс символ начала пакета в пакете
					indexBeginCharInPackage = i;
					break;
				case endChar:
					// Получаем индекс символ конца пакета в пакете
					indexEndCharInPackage = i;
					break;
				case breakChar:
					// Получаем кол-во символов разделителя блоков данных в пакете
					breakCharCountInPackage++;
					break;
				default:
					// В зависимости от номера блока данных в пакете, заполняем переменные блоков
					switch (breakCharCountInPackage) {
						case 0:
							// Номер пакета в системе
							numberPacket += receiveCharArrayCOM[i];
							break;
						case 1:
							// Длина пакета
							lenPacket += receiveCharArrayCOM[i];
							break;
						case 2:
							// Тип операции пакета
							operationTypePacket += receiveCharArrayCOM[i];
							break;
						case 3:
							// Тип операции пакета
							parametrPacket += receiveCharArrayCOM[i];
							break;
						case 4:
							// Тип данных параметра пакета
							dataTypePacket += receiveCharArrayCOM[i];
							break;
						case 5:
							// Значение параметра пакета
							valuePacket += receiveCharArrayCOM[i];					
							break;
					} 
					break;
			}
		}
       
		if (breakCharCountInPackage != 5)
		{
			ErroreDataReceived("2",1);

			return;
		}
		
		// Номер пакета в системе, Int
		receiveNumberIntPacket = numberPacket.toInt();

		// Номер пакета в системе, Int
		receiveLenIntPacket = lenPacket.toInt();

		// Тип операции пакета, Int
		receiveOperationTypeIntPacket = operationTypePacket.toInt();

		//SerialPrintLine(String(indexBeginCharInPackage));
		//SerialPrintLine(String(breakCharCountInPackage));
		//SerialPrintLine(String(indexEndCharInPackage));
		//SerialPrintLine(String(receiveLength));
		//SerialPrintLine(String(receiveLenIntPacket));

		// Проверка корректности полученного пакета 
		if (indexBeginCharInPackage == 0 && breakCharCountInPackage == 5	// Индекс символа начала пакета, должен быть равен 0, кол-во блоков данных должно быть 5	
				&& indexEndCharInPackage == (receiveLength - 1)				// Индекс символа конца пакета, должен быть равен значению блока длины пакета - 1
				&& receiveLenIntPacket == receiveLength						// Реальная длина пакета должна быть равна значению блока длины пакета
				)
		{
			// Определяем тип операции пакета
			switch(receiveOperationTypeIntPacket)
			{
				case OT_StartTPA:
					// Старт ТПА

					SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());

					// Устанавливаем состояние программы запущена
					beginWorkTPA = true;
					break;	
				default:
					int globalNumberPacketAndOne = globalNumberPacket;//globalNumberPacket + 1;
					if (receiveOperationTypeIntPacket != OT_CheckReturnFromPC && receiveNumberIntPacket == globalNumberPacketAndOne)
					{			
						SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());
					}
					else 
					{
						if (receiveNumberIntPacket == globalNumberPacketAndOne)
						{
							switch(receiveOperationTypeIntPacket)
							{
								case OT_StopTPA:
									// Стоп ТПА
							
									SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt());
								
									//globalNumberPacket = 0;

									// Устанавливаем состояние программы остановлена
									beginWorkTPA = false;
									break;
							}
						}
						else 
						{
							ErroreDataReceived("3",0);
						}
					}		
					break;
			}
		}
		else 
		{
			ErroreDataReceived("4",0);
		}              								
	}
}
/******************************  /Функции работы с полученными данными  **********************************/

/******************************  Функции работы с ошибками  **********************************/
/// <summary>
/// Ошибка получения данных
/// </summary>
void ErroreDataReceived(String DataReceived, int TypeErrore)
{
	// TODO: Добавить описание 
	ClearReceiveDataVariable();

	Errore(DataReceived, 0);
}

/// <summary>
/// Ошибка получения данных
/// </summary>
void Errore(String Data, int TypeErrore)
{
	// TODO: Добавить описание 
	//FullStopTPA();

	Log(Data, TypeErrore, true);
}
/******************************  /Функции работы с ошибками  **********************************/

/******************************  Функции работы с логом  **********************************/
/// <summary>
/// Логирование
/// </summary>
void Log(String Data, int TypeLog, bool isErrore)
{
	// TODO: Добавить описание 
	switch (connectionType) 
	{
		case CT_Serial:
			SerialPrintLine(Data);
			break;
	}
}
/******************************  /Функции работы с логом  **********************************/

Работает стабильно. 
Пока не дополнял доп. проверками и не наводил порядок.

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

Artur1985
Offline
Зарегистрирован: 19.02.2013

Нашел ошибку у себя в C#, кроме потоков. Неправильная инициализация соединения.
Как должно быть.

 

            ArduinoSerialPort.PortName = "COM25";
            ArduinoSerialPort.BaudRate = 115200;

            ArduinoSerialPort.Parity = Parity.None;
            ArduinoSerialPort.DataBits = 8;
            ArduinoSerialPort.StopBits = StopBits.One;

            ArduinoSerialPort.Encoding = Encoding.UTF8;

            ArduinoSerialPort.NewLine = "\n";

            ArduinoSerialPort.RtsEnable = false;
            ArduinoSerialPort.DtrEnable = true;

            ArduinoSerialPort.DataReceived += new SerialDataReceivedEventHandler(ArduinoSerialPort_DataReceived);

            ArduinoSerialPort.Open();

Не хватало
ArduinoSerialPort.RtsEnable = false;
ArduinoSerialPort.DtrEnable = true;

Если не установить эти настройки, будут проблемы. При первой отправке на ардуину к запросу будет добавляться мусор, могут быть и другие проблемы.