Arduino.Serial + Qt5: Сказ о том, как генералы пустой буфер получали
- Войдите на сайт для отправки комментариев
Пт, 12/02/2016 - 07:59
Нужно передавать на ардуинку дамп hex-файлов из компа. Желательно делать это быстро, решительно. Взял Мегу 2560. Наваял прожект на Qt, прицепил к Ардуинке, передаю куски по 16 байт (там же 64 байта в Serial кеш). На деле же получается весьма плачевно: принимается каждая третья передача, при этом ещё и портится. Что я делаю не так?
void setup() { Serial.begin(115200); } long prog_size =0; void loop() { ++prog_size; byte inbuffer[48] = {0}; Serial.write((byte)1); while(!Serial.available()); Serial.readBytes(inbuffer,1); memset(inbuffer,0,48); Serial.write(2); Serial.write((byte*)&prog_size,4); while(!Serial.available()); Serial.readBytes(inbuffer,16); Serial.write(3); Serial.write((byte*)&prog_size,4); Serial.write(inbuffer,16); }
void MainWindow::on_comboBox_currentIndexChanged(int index) { if (index < 0) return; if (port) port->deleteLater(); port = new QSerialPort(ui->comboBox->itemText(index)); port->setBaudRate(QSerialPort::Baud115200); port->open(QIODevice::ReadWrite); connect(port,SIGNAL(readyRead()),SLOT(PortInput())); } void MainWindow::PortInput() { quint8 command = (quint8)port->read(1).data()[0]; qDebug() << "command" << command; if (command == 1) { port->write((char*)&(rom.prgPagesCount),1); qDebug() << "size" << rom.PagesCount; } if (command == 2) { quint32 offset = port->read(4).toUInt(); QByteArray buffer = rom.Pages[offset/BANK_SIZE].mid(offset%BANK_SIZE,16); port->write(buffer.data(),buffer.size()); qDebug() << "buffer" << buffer; } if (command == 3) { QByteArray buffer = port->read(4); qDebug() << "offset" << buffer; qDebug() << "buffer" << port->read(16); } }
command 1 size 1 command 2 buffer "L\f\xE8\xA5h)\x02\xF0\x01`\xA2\x00\x86m\xB5`" command 3 offset "\x01\x00\x00\x00" buffer "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" command 1 size 1 command 2 buffer "L\f\xE8\xA5h)\x02\xF0\x01`\xA2\x00\x86m\xB5`" command 3 offset "\x02\x00\x00\x00" buffer "\f\xE8\xA5h)\x02\xF0\x01`\xA2\x00\x86m\xB5`\x00"
Дык на момент чтения в буфере данные есть? Или читаешь абы читать?
Попробуй в настройках порта в скетче поставить два стоповых бита вместо одного.
Дык на момент чтения в буфере данные есть? Или читаешь абы читать?
А разве там не стоит isAvailable?
Попробуй в настройках порта в скетче поставить два стоповых бита вместо одного.
А можно глупый вопрос? А как? Точнее, где прочитать, какой из параметров config в Serial.begin(speed, config) что означает. ибо после документации Qt чтение таковой на СС оставило впечатление посещения "Зелёного слоника".
Во втором куске кода я ничего подобного не вижу, потому и спрашиваю.
SERIAL_8N2
Только для хардварного Serial.
8 бит данных
Без контроля четности
2 стоповых бита
Arduino\hardware\arduino\avr\cores\arduino\HardwareSerial.h
Нет, не в этом дело. Даже если это и изменило ситуацию к лучшему, уж точно не кардинально.
1) quint32 i = port->read(4).toUInt(); не отрабатывал, но quint32 i; memcpy(&i,port->read(4).data(),4); отрабатывает на ура. Сраная техномагия.
2) Помогает delay(20); Serial.flush(); после больших кусков данных. Такой мерзкий велосипед, аж во рту пересохло... А, не, это кальмары.
3) Никак не влияют паузы или, наоборот, ускорение работы с портом на стороне ПК. Мерзость!
В целом, я заставил эту хрень работать. Но ощущения жутко негативные. Целиком. Я прекрасно понимаю, что я ничего не понимаю, но я даже не понимаю, что мне нужно понять для того, чтобы понимать то, что я сейчас не понимаю. Иными словами, у этой техномагии есть нормальный кодекс?
Или у тебя мусор посылается, или не всё вычитываешь из буфера.
Сложно не вычистить буфер, который создаёся на стеке и заполняется нулями. Проблема, видимо, была в том, что буфер порта переполнялся раньше окончания считывания. А может и нет. В душе не держу. Факт в том, что паузы после записи и очистка хардварного буфера помогает. ( А ведь flush прежде всего об этом, нэ?)
Для начала сюда: https://www.arduino.cc/en/Serial/Read
Смысл написанного сводится к тому, что чтение происходит побайтово. То есть за один раз ты можешь передать только один байт. То есть: например число int от 0 до 255.
Для преодоления данного препятствия специально-обученные самизнаетекто(к коим отношусь и я) понаписали кучу всякого непотребства называемом "библиотеки" или "либы", не путать с "лыбой".
Посмотри вот это моё творение, библиотека для ардуино и для процессинга(Java) для обмена данными правда под кью-ти нет, варианта, но с небольшим допиливанием, должна подойти библиотека от собственно ардуино(потребуется исправить serial-функции приёма-передачи данных в сторону Qt).
Окунись в код, ознакомься с примерами: http://arduino.ru/forum/programmirovanie/arduino-rasshirennaya-peredacha...
Для начала позвольте вас отблагодарить, капитан, ваши услуги незаменимы!
Затем - сюда: https://www.arduino.cc/en/Serial/ReadBytes Смысл написанного сводится к тому, что Serial может в передачу-приём блоков данных. А любая книжка по Си скажет, что с точки зрения процессора все эти ваши инты - просто 2 WORD или 4 BYTE, которые можно скормить в сыром виде в memcpy. Более того, available передаёт размер уже прибывшего буфера, и мы можем сидеть и ждать данные для чтения. Так что проблема была не в этом. (Кстати, ваша библиотека была бы куда умнее, если бы могла паковать 10-битные значения с использованием сдвигов. И если бы использовала 2^n размеры полей, а не 10^m, потомучто)
Далее - окунаемся сюда https://ru.wikipedia.org/wiki/RS-232 И узнаём, что у последовательных портов есть уйма параметров передачи: скорость потока, число бит данных, стоповые биты, проверка чётности и тп. А так же банальная разница скоростей ардуины и ПК, ведь первая могла не успеть переварить все данные, а второй - отреагировать. Именно в этом разделе у меня и был вопрос, как их настроить и на какой скорости.
Следующий пункт - Qt. Учитывая то, что QSerialPort - сторонняя шлюпка, прибитая к гиганту волнами, есть все причины полагать, что в нём есть баги или, как минимум, недосказанности в документации, о которых мне могли бы рассказать опытные товарисчи.
Очень позабавил ваш PR вашего, кхм, творения. Я не претендую на звание "Программист года" даже в той фирме, на которую работаю, но даже мне с ходу видны... как бы это помягче... Неподготовленность вашей библиотеки к внешнему миру. Вы больше не отца, а сутенёра напоминаете, который лолитками торгует. Такого, знаете, классического американского, всего в золоте, шубах и дешёвых понтах. Для начала ознакомьтесь с нормальным тоном разметки, где public:, к примеру, будет стоять на один уровень раньше методов и полей. Это САМОЕ базовое замечание, а их больше, чем байт в ваших исходниках. Ну и вообще, странно, человек на Qt пишет, а ему processing подкладывают.
Так, что-то меня понесло. Ах, это мои рабы. Успеть бы жмакнуть "Сохранить", пока рука дотягивается.
Для реализации того, что Вы здесь нагородили, об умности библиотеки, и возможностях RS232 следует отказаться от библиотеки serial и использовать свою собственную.
я же предложил лишь надстройку над serial, чтобы не лепить собственные костыли. От ардуино бОльших возможностей и не требуется.
Вам шашечки или ехать?
Что же касается вашего бахвальства про программирование на Qt, то во первых: я "подкладывал" не Processing а исходники библиотеки от Arduino ибо Processing это джава, и я по рассеяности не положил исходник библиотеки в архив, да это и смысла не имеет, так как кто способен собрать, тот им сам такое напишет заглянув в сорцы "ардуино", а кто не способен, тому там делать нечего.
Ваш уничижительный тон по отношению к другому языку, выдаёт в Вас непрофессионала.
Например я года три не вылазил из KDevelop, я ведь не смотрю на Вас и Ваше Qt как на говно. Хотя Вы вполне этого заслуживаете за Ваши поползновения оскорбить меня сутенёром.
))))
В строке 17 делать проверку available()<16. Сейчас у Вас из цикла выходит при наличии в бухере хоть чего. И его мало.
В строке 17 делать проверку available()<16. Сейчас у Вас из цикла выходит при наличии в бухере хоть чего. И его мало.
Приведите практический пример некорректности работы библиотеки.
Буду Вам очень признателен.
В строке 17 делать проверку available()<16. Сейчас у Вас из цикла выходит при наличии в бухере хоть чего. И его мало.
Чего?! Это не либа некоректно работает, это ТС её неверно использует. Строки17-18 как раз и есть примером. available() возвращает кол-во реально принятых на момент вызова байт.
Не хочу вникать в библиотеку serial Вы могли бы обрисовать условия, при которых Christina дала бы сбой?
Проверяй количество данных в буфере перед чтением!
Так и я не хочу вникать в Christina. Вобще с чего о ней речь? ТС сделал на стандартной Serial, но напутал с проверкой. Ошибка легко исправима, о чем ему и написал я. Какая такая Christina?! Зачем она здесь?
Проверяй количество данных в буфере перед чтением!
Logik, Radjah, увы, это ничего не даёт. Даже если допустить, что я сжираю только первый символ, они не совпадают ни одним битом.
Так что дело действительно либо в настройках передачи, либо в задержках работы программы на ПК. (Это не голословное заявление, я только что встал и проверил. Тухло.)
allesanbr > Для реализации того, что Вы здесь нагородили, об умности библиотеки, и возможностях RS232 следует отказаться от библиотеки serial и использовать свою собственную.
Для реализации вашего барахла неплохо было бы изучить битовые поля у структур.
allesanbr > я же предложил лишь надстройку над serial, чтобы не лепить собственные костыли. От ардуино бОльших возможностей и не требуется.
А вас об этом просили? Вы, вообще, поняли о чём вопрос? Хотя бы после разжёвывания? Не похоже.
allesanbr > Вам шашечки или ехать?
Мне автомобиль.
allesanbr > Что же касается вашего бахвальства... и прочий баттхёрт.
Мне глубоко (как бы это поуважительнее к остальной публике сказать) поровну на все языки программирования. Их тысячи, они приходят и уходят, одни я изучаю(-л), другие - даже не имею представления об их существовании. Меня интересует конкретная проблема и её конкретное решение. И то, что это решение должно быть приближено к Qt я обозначил в самом первом посте.
Вы же прилепили дерьмовую, буду честным, библиотеку по передаче 10 бит в виде 4 (четырёх, Карл!) байт, которые считываются с аналогового пина. Чёрт подери, я во второй вечер от скуки сделал осциллограф с отрисовкой графика, просто потому, что мне было скучно, но я же этот говнокод не пихаю людям. Я же знаю, что в интернетах есть исходники на пару порядков круче моего. А сейчас я хочу сделать программатор для M27C2001, просто потому как с наскока не нашёл. И именно в передаче больших массивов я и спустил обойму в собственную ногу. Конечно, больших массивов можно избежать, но проблема уже появилясь и она настойчиво требовала моего внимания. А как говорил один герой экрана, "не мы властны над нашим разумом".
allesanbr > оскорбить меня сутенёром.
Тупым американским сутенёром с дешёвыми понтами и несовершеннолетним товаром. Мне больше нравится эта полная формулировка. И, поверьте, я познакомился с вашими постами\комментариями\опусами перед тем, как составить такое мнение.
Всё, сомненья развеяны, всё дело в задержках Qt. Всё взаимодействие нужно вывести в отдельный поток, так как GUI вносит критичные, в данном случае, задержки в работу "протокола".
Всё, сомненья развеяны, всё дело в задержках Qt. Всё взаимодействие нужно вывести в отдельный поток, так как GUI вносит критичные, в данном случае, задержки в работу "протокола".
То есть Вы стесняетесь даже свои собственные алгоритмы взаимодействия между устройствами называть - протокол. И берёте это слово в кавычки?!
Да у Вас мания ничтожества!
)))
Поэтому: Естественно для Вас всё - говно. Даже Вы сами.
Так вот дорогой друг, я Вам открою тайну:
Можете не ставить кавычки вокруг слова - протокол, если речь идёт об алгоритмах взаимодействия между двумя устройствами. Я Вам больше скажу: даже между двумя программами!!! Это слово как раз и говорит нам о том, что речь идёт о неких соглашениях об обмене данными между чем-то и чем-то.
На то, что Вы думаете обо мне лично - мне абсолютно фиолетово, а вот у Вас есть большие проблемы с самооценкой.
Что же касается четырёх (...Карл!) байт, то даже 9600 бод это скорость в такое количество раз превышающая реакцию любого аналогового датчика, что на конечном результате это не отражается - от слова - никак.
Кстати в отличии от настоятельно рекомендуемого ардуино delay(); при работе с аналоговыми пинами. Учите матчасть!
allesanbr> На то, что Вы думаете обо мне лично - мне абсолютно фиолетово
Тогда почему у вас так лихо припекает снизу, что аж до "комплексов ничтожества" дошло? Это, батенька, ложь, вам очень хочется похвалы. А её нет. Даже если у меня такой комплекс есть, вас не смущает то, что с высоты этого комплекса я смотрю на вас сверху? Вы себя загоняете в угол, батенька.
allesanbr> Что же касается четырёх (...Карл!) байт, то даже 9600 бод это скорость в такое количество раз превышающая реакцию любого аналогового датчика, что на конечном результате это не отражается - от слова - никак.
16 аналогов, 11 шимов, 24 пина, 3 хардварных порта и, конечно, I2C. Обыкновенная Мега. Если разбрасываться операциями так, как вы советуете, то половина из перечисленного нафиг не сдалась, а вторая будет дико лагать, ибо имеем мы всего 14 МГц. Кстати, как ваша библиотека, может в несколько портов одновременно?
Слава яйцам коня Тамерлана! Хоть один вопрос по теме.
Нет не может в несколько портов. Так как я во время решения задачи, просто не знал о serial-возможностях "меги".
Учитывая что:
"Для Arduino Mega: Serial1, Serial2, Serial3"
То она может и не работать на "меге". В исходники класса Serial пока не заглядывал(сюрприз будет) ;)
А теперь, если можно, прекратите писать в этой теме. Ваш "код" мне абсолютно не интересен, никакой полезной нагрузки вы не несёте, а посраться лучше на политических форумах.
А теперь, если можно, прекратите писать в этой теме. Ваш "код" мне абсолютно не интересен, никакой полезной нагрузки вы не несёте, а посраться лучше на политических форумах.
С удовольствием выполняю Вашу просьбу.
...а насчёт самооценки, Вы всё же подумайте. У Вас в двух предложениях подряд - два слова "я", и одно слово "мне".
Это звоночек.
Не говоря уже о том, что Вы пытаетесь поставить себя выше собеседника.
Всего хорошего.