Передача данных с Ардуино в С# без задержки возможна?

zyto
Offline
Зарегистрирован: 21.03.2014

Имеем: Arduino UNO R3, соединено по USB с компом, на компе Visual Studio 2013, C#, ну и наверно .Net 2

Код ардуино:

#define R 10//правый светодиод висит на 10м пине
#define res A5//переменный резистор на А5

int pos = 0;//текущее "значение" резистора
int calc = 0;//значение яркости для светодиода

void setup()
{
	Serial.begin(115200);//открываем порт на максимальной скорости
	//настраиваем порты:
	pinMode(R, OUTPUT);
	pinMode(L, OUTPUT);
	pinMode(res, INPUT);
}

void loop()
{	
	//получаем данные с резистора
	pos = analogRead(res);
	calc = pos / 4;//подгоним для вывода на светодиод (т.к. pos = 0-1023)

	Serial.print(calc);//отправляем в комп данные
	analogWrite(R, calc);//зажигаем светодиод
	delay(10); //ждём
}

Код C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace Reading3
{
    public partial class Form1 : Form
    {
        SerialPort port = new SerialPort("COM4", 115200, Parity.None, 8, StopBits.One);
        public Form1()
        {
            InitializeComponent();

            port.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);            
            port.Open();
        }

        private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            textBox1.Text = port.ReadExisting();
        }    

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            port.Close();
        }        
    }
}

В таком виде (с некоторой задержкой - 10мс) всё более-менее отображается:

Хотя иногда бывает проскакивают какие-то левые числа, но их не так много...

А вот если убрать задержку, или поставить delay(1) - то видим очень интересную картину:

Т.е. одно и то же число отображается по несколько раз...

 

Не могу понять в чём проблема? Неужели нельзя передавать данные в реальном времени, и обязательно нужны задержки? Или где ещё поковырять/посмотреть?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну что за удивительный вопрос ?! Вы же сами отправляете бесконечное число раз текстовую строку неопределенной длинны. У вас даже между отправками никакого признака разделения нет ! Собственно... что отправляете, то и получаете. Ваши программы работают именно так как написанны !

zyto
Offline
Зарегистрирован: 21.03.2014

Ок. Как лучше сделать?
Отправлять символ окончания строки ('\n', если не ошибаюсь), или как-то по другому отправлять данные?
Если по другому - то как лучше?

 

zyto
Offline
Зарегистрирован: 21.03.2014

PS Попробовал вместо

 Serial.print(calc);

написать

Serial.println(calc);

Насколько я понимаю, этот метод должен дополнять передаваемые данные символами перевода строки и возврата каретки...

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

 

А как вообще можно передать не строку а целое или дробное число?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Оканчвайте отправку значения любым байтом, например 0x0d или 0x0a или 0 и поймав этот байт на принимающей стороне обработайте строку и сбросьте все принятые данные, освободив место для новой посылки. Если мне не изменяет память то "/n" это два байта 0х0a (возврат каретки, курсор вернется в нулевую позицию) и 0х0d (перевод строки, курсор переместится на строку ниже не изменив позиции в строке).

zyto
Offline
Зарегистрирован: 21.03.2014

Мде... теперь вопросов стало ещё больше :)
Поиду чё-нибудь погуглю...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ок.. раз самому так сложно... отправляйте serial.println(calc), принимайте port.readline(). :-)

zyto
Offline
Зарегистрирован: 21.03.2014

Пробовал... не помогает...

При если поставить задержку 1 или вообще убрать - данные на форме обновляются спустя относительно продолжительное время (от нескольких секунд и больше), если поставить задержку 2 и больше - данные на форме обновляются мгновенно...

Странно это как-то.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

zyto
Offline
Зарегистрирован: 21.03.2014

Сделал вот так:
 

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {            
            textBox1.Text = port.ReadLine();
        }    
void loop()
{	
	//получаем данные с резистора
	pos = analogRead(res);
	calc = pos / 4;//подгоним для вывода на светодиод (т.к. pos = 0-1023)

	Serial.println(calc);//отправляем в комп данные
	analogWrite(R, calc);//зажигаем светодиод
	delay(1); //ждём
}

Тормозит жутко. Но если поставить delay хотя бы 2 и больше - всё летает...

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

Летает = данные обновляются одновременно с поворотом резистора, задержек на глаз не заметно.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ясно... Событие ondatareceived происходит в момент получения первого байта пакета. Попробуйте найти событие которое происходит при получении полной строки или при полуении каждого байта. И еще при получении проверяйте длинну строки и если она пустая просто выходите из подпрограммы. Еще нюанец вы измеряете много чаще чем данные успевают убежать по ком порту, поэтому вам и приходится использовать задержку. 

zyto
Offline
Зарегистрирован: 21.03.2014

Т.е. возможен вариант, что 1 мс - это время, за которое 1 байт проходит полный путь? И остаётся только смириться?

zyto
Offline
Зарегистрирован: 21.03.2014

...других событий я не наблюдаю:

http://msdn.microsoft.com/ru-ru/library/system.io.ports.serialport_events(v=vs.110).aspx

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Один бай при последовательной передаче на скорости 9600бод один байт уходит за 0.00115 секунды, что соответствует 1.15 миллисекунде. У вас отправляется после каждого измерения минимум два байта. Судя по всему вы используете для передачи хардварный порт. Что вам мешает поднять скорость передачи до 115000 ? Если умеете использовать нестандартные скорости передачи ставьте 200000, это максимальная скорость для ардуино на16мгц кварце. Если же юзаете усбишный виртуальный ком порт, то могу утверждать, что он волшебно летает на 500000 бод.

Под виндой у вас правильное событие, происходит каждый полученный байт. Бал не внимателен. Какой то у вас апи простейший :-)

zyto
Offline
Зарегистрирован: 21.03.2014

Ну у меня вроде и так:

Serial.begin(115200);

SerialPort port = new SerialPort("COM4", 115200, Parity.None, 8, StopBits.One);

 

т.е. было на 115200.

Поставил 500000, ничего не изменилось... Ну собственно и фиг с ним, наверно 1-2 милисекунды не так критично...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

На скорости 115200 байт уходит за 10 микросекунд.

alex6441161
Offline
Зарегистрирован: 31.01.2015

Здравствуйте, передаю данные от микроконтроллера в ПК по COM порту, в терминалке все норм приходит, а вот если сам пишу прогу на C# то нифига не получается. Почему-то не обрабатывается метод OnDataReceived. В чем может быть проблема?