Форум программистов, компьютерный форум, киберфорум
Наши страницы
Arduino
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
Astronomax
0 / 0 / 0
Регистрация: 12.06.2018
Сообщений: 8
1

C++ отправка команд на ардуино через com порт посредством библиотеки windows.h

14.04.2019, 22:08. Просмотров 1134. Ответов 32
Метки нет (Все метки)

Добрый день!
Возникла проблема, с которой сам разобраться не могу.
Хотел сделать консольное приложение на c++, которое бы отправляло какой-то текст через com-порт на ардуино.
Погуглил данную тему и узнал, что это можно сделать используя библиотеку windows.h.
Для теста придумал себе такую задачу: нужно отправить какой угодно текст в com-порт, а ардуино, получив его, должна
включить 13 пин и не выключать больше.
Вот код для ПК на C++;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <cmath>
#include <functional>
#include <algorithm>
#include <utility>
#include <stack>
#include <unordered_map>
#include <iterator>
#include <fstream>
#include <iomanip>
#include <windows.h>
 
using namespace std;
 
#define X real()
#define Y imag()
#define timer fghge
#define y1 yjyjyju
#define all(X) (X).begin(), (X).end()
#define int long long
#define double long double
 
signed main() {
    HANDLE hSerial;
    LPCTSTR sPortName = L"COM5";
    hSerial = ::CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hSerial == INVALID_HANDLE_VALUE){
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
            cout << "serial port does not exist.\n";
        cout << "some other error occurred.\n";
    }
    DCB dcbSerialParams = { 0 };
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams))
        cout << "getting state error\n";
    dcbSerialParams.BaudRate = CBR_9600;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams))
        cout << "error setting serial port state\n";
   
    char data[] = "a";  // строка для передачи
    DWORD dwSize = sizeof(data);   // размер этой строки
    DWORD dwBytesWritten;    // тут будет количество собственно переданных байт
 
    BOOL iRet = WriteFile(hSerial, data, dwSize, &dwBytesWritten, NULL);
 
    cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
    CloseHandle(hSerial);
    return 0;
}
На дефайны внимание не обращайте, это моё.
А вот код для ардуино.
C++
1
2
3
4
5
6
7
8
9
10
11
void setup() {
        Serial.begin(9600); // устанавливаем последовательное соединение
        pinMode(13, OUTPUT);
    }
 
 
    void loop() {
        if (Serial.available() > 0) {  //если есть доступные данные
            digitalWrite(13, HIGH);
        }
    }
И вроде все работает, в консоль пишет, что передано 15 байт из 15 переданных, сообщений об ошибках нет.
Проблема такая: когда запускаю отправку с ПК, только что после того, как загрузил прошивку в ардуину, все работает (светодиод загорается и не гаснет), но когда это делаешь повторно и даже после того, как переподключишь, ардуину к com-порту, светодиод загорается на какое-то мгновение, а затем гаснет.
Сначала я думал, что это из за того, что программа на c++ завершается и ардуино, как-бы перезапускается, попробовал поставить точку останова перед командой закрытия порта и return 0, и запустить код в отладчике, но это не помогло, результат остался тем же.
Прощу помощи у вас, буду благодарен за любые предположения.
Если нужно больше информации, пишите.

Добавлено через 12 минут
Причем мигает он тогда не по причине того, что я отправляю данные в com-порт, это обычное моргание светодиода на плате при подключении ардуины к компу / перезапуске скетча.
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.04.2019, 22:08
Ответы с готовыми решениями:

Контроль ардуино через порт
Я посмотрел видос, сделал точь в точь. У меня ардуино мега2560. Хотел написанием текста через порт...

Отправка SMS посредством АТ команд через мобильник
Доброго всем времени суток!!! Пречитал кучу инфы. но так и непонял как отправку реализовать в...

Можно ли через ардуино по USB посредством кнопки или сенсора включить или выключить монитор компютера?
Можно ли через ардуино по USB при помощи кнопки или сенсора включить или выключить монитор...

Отправка команд на сервер через браузер
Здравствуйте, уважаемые форумчане! :) Есть идея, но как реализовать не знаю, подскажите...

Отправка команд через Steam API
Ребят,не могу понять почему не хочет слать команду на пользователя. Суть проблемы: Работаю через...

32
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
14.04.2019, 23:21 2
Поставь себе Qt и используй QtSerialPort.
С WinApi долго будешь разбираться.

Добавлено через 23 секунды
Цитата Сообщение от Astronomax Посмотреть сообщение
используя библиотеку windows.h.
Не путай библиотеку и заголовочный файл.
1
Astronomax
0 / 0 / 0
Регистрация: 12.06.2018
Сообщений: 8
15.04.2019, 14:04  [ТС] 3
ОШИБКУ Я НАШЕЛ!!! Оказывается данные в ком порт надо было слать с некоторой задержкой и тогда всё работает.
То есть когда я запускал код на c++, запускался скетч на ардуино и в это же время с++ слал данные в порт. Не знаю точно, что происходит в "мозгах" ардуины когда ее включают, возможно она просто не успела обработать блок setup(), когда я уже отправил ей данные. Если кто-то может точно объяснить, что произошло, и почему временная задержка помогла, буду благодарен, если напишите.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <cmath>
#include <functional>
#include <algorithm>
#include <utility>
#include <stack>
#include <unordered_map>
#include <iterator>
#include <fstream>
#include <iomanip>
#include <windows.h>
 
using namespace std;
 
#define X real()
#define Y imag()
#define timer fghge
#define y1 yjyjyju
#define all(X) (X).begin(), (X).end()
#define int long long
#define double long double
 
signed main() {
 
    HANDLE hComm;
    LPCTSTR sPortName = L"COM3";
    hComm = CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 
 
    if (hComm == INVALID_HANDLE_VALUE)
        printf("Error in opening serial port");
    else
        printf("opening serial port successful");
 
    DCB dcbSerialParams = { 0 }; // Initializing DCB structure
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
 
    dcbSerialParams.BaudRate = CBR_9600;  // Setting BaudRate = 9600
    dcbSerialParams.ByteSize = 8;         // Setting ByteSize = 8
    dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1
    dcbSerialParams.Parity = NOPARITY;  // Setting Parity = None
 
    char lpBuffer[] = "A";
    DWORD dNoOFBytestoWrite;         // No of bytes to write into the port
    DWORD dNoOfBytesWritten = 0;     // No of bytes written to the port
    dNoOFBytestoWrite = sizeof(lpBuffer);
    Sleep(2000);
    WriteFile(hComm, lpBuffer, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL);
    
    CloseHandle(hComm);
    return 0;
}
Просто добавил Sleep(2000), чтобы подождать пока ардуина сделает, все что ей нужно при запуске (проморгает всеми светодиодами).
0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
15.04.2019, 14:37 4
Цитата Сообщение от Astronomax Посмотреть сообщение
ОШИБКУ Я НАШЕЛ!!! Оказывается данные в ком порт надо было слать с некоторой задержкой и тогда всё работает.
Это не ошибка.
0
15.04.2019, 14:37
Astronomax
0 / 0 / 0
Регистрация: 12.06.2018
Сообщений: 8
15.04.2019, 14:41  [ТС] 5
Цитата Сообщение от Avazart Посмотреть сообщение
Сообщение от Astronomax
ОШИБКУ Я НАШЕЛ!!! Оказывается данные в ком порт надо было слать с некоторой задержкой и тогда всё работает.
Это не ошибка.
А что это тогда? Как только я это исправил, Светодиод стал загораться и пин RX ардуин стал мигать, то есть данные приходят теперь.
0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
15.04.2019, 14:49 6
Цитата Сообщение от Astronomax Посмотреть сообщение
А что это тогда?
Полное непонимание того что делаешь...
0
Astronomax
0 / 0 / 0
Регистрация: 12.06.2018
Сообщений: 8
15.04.2019, 14:53  [ТС] 7
Цитата Сообщение от Avazart Посмотреть сообщение
Полное непонимание того что делаешь...
Ну напишите, тогда, что я сказал не так, раз понимаете. Я только недавно этот вопрос начал изучать, многое не понимаю.
0
locm
2224 / 943 / 121
Регистрация: 28.10.2011
Сообщений: 3,120
Записей в блоге: 6
15.04.2019, 15:29 8
Лучший ответ Сообщение было отмечено Astronomax как решение

Решение

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

Другая причина в том что используется вывод DTR COM порта для сброса МК и при выполнении CreateFile на этом выводе может установится логический уровень, приводящий к перезагрузке. Это не раз было замечено на практике.
1
Astronomax
0 / 0 / 0
Регистрация: 12.06.2018
Сообщений: 8
15.04.2019, 15:37  [ТС] 9
Цитата Сообщение от locm Посмотреть сообщение
При включении питания или сбросе, перед выполнением кода некоторое время работает загрузчик. Если сразу отправить команду ее примет загрузчик, а не ваш код.
Другая причина в том что используется вывод DTR COM порта для сброса МК и при выполнении CreateFile на этом выводе может установится логический уровень, приводящий к перезагрузке. Это не раз было замечено на практике.
Спасибо, понял.
0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
15.04.2019, 15:48 10
Цитата Сообщение от locm Посмотреть сообщение
Другая причина в том что используется вывод DTR COM порта для сброса МК
Это зависит от того как настроишь ком порт имею ввиду в коде С++ c WinApi.

Добавлено через 56 секунд
Цитата Сообщение от Astronomax Посмотреть сообщение
Ну напишите, тогда, что я сказал не так, раз понимаете. Я только недавно этот вопрос начал изучать, многое не понимаю.
Ваш гавнокод не достоит того что бы на него смотреть. Учите С++ разбирайтесь с WinApi тогда можно будет о чем то говорить.
0
locm
2224 / 943 / 121
Регистрация: 28.10.2011
Сообщений: 3,120
Записей в блоге: 6
15.04.2019, 16:41 11
Цитата Сообщение от Avazart Посмотреть сообщение
Это зависит от того как настроишь ком порт имею ввиду в коде С++ c WinApi.
Все не так просто. Уровень на DTR будет изменен при выполнении CreateFile. Изменить его состояние можно функцией SetCommState или EscapeCommFunction, но им нужен дескриптор порта, т. е. без CreateFile не обойтись, но ее выполнение может изменить уровень на DTR и МК перезагрузится.
0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
15.04.2019, 16:59 12
Не знаю я делал это на практике. Причем в коде на питон. И работало.
0
marat_miaki
190 / 167 / 99
Регистрация: 08.04.2013
Сообщений: 692
15.04.2019, 20:21 13
Astronomax, Думаю для работы с сом портом вам для начала подойдет этот проект для MSVStudio С++ 2008 или 2010, нашел где то в сети.
0
Вложения
Тип файла: zip ComPort.zip (22.7 Кб, 3 просмотров)
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
15.04.2019, 22:54 14
Да в сети куча разнова хлама, я бы не советовал, лучше сразу брать Qt.

Добавлено через 2 минуты

Не по теме:

Я кстати тоже велосипеды строил https://github.com/Avazart/Bicycle/tree/master/Bicycle/Win/Serial

0
locm
2224 / 943 / 121
Регистрация: 28.10.2011
Сообщений: 3,120
Записей в блоге: 6
16.04.2019, 15:11 15
Цитата Сообщение от Avazart Посмотреть сообщение
лучше сразу брать Qt.
Жирные проги получаются и GUI нестандартный (отличается от текущей темы ОС). На мой взгляд для простых программ не самый подходящий.

Не по теме:

Если не ограничиваться плюсами, задачу можно решить гораздо проще. Аналог кода из первого сообщения.

PureBasic
1
2
3
4
If OpenSerialPort(0, "COM1", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 255, 255)
  WriteSerialPortString(0, "a", #PB_Ascii)
  CloseSerialPort(0)
EndIf

0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
16.04.2019, 15:31 16
Цитата Сообщение от locm Посмотреть сообщение
Жирные проги получаются и GUI нестандартный (отличается от текущей темы ОС). На мой взгляд для простых программ не самый подходящий.
В смысле жирные?
И чем это GUI нестандартный? Вполне нормальны GUI даже лучше стандартного.
Да и в чем суть? Суть в связи GUI + SerialPort + потоки.

А если это не надо, то для "простых" лучше - Python.

Не по теме:

А PureBasic это # отстой.

0
locm
2224 / 943 / 121
Регистрация: 28.10.2011
Сообщений: 3,120
Записей в блоге: 6
16.04.2019, 15:51 17
Цитата Сообщение от Avazart Посмотреть сообщение
В смысле жирные?
Проги с рантаймом верят несколько десятков метров. В винде по умолчанию рантайма для Qt нет.

Цитата Сообщение от Avazart Посмотреть сообщение
Вполне нормальны GUI даже лучше стандартного.
Нестандартный в том смысле что отличается от текущей темы ОС. Выглядит по другому. Я об этом написал.

Цитата Сообщение от Avazart Посмотреть сообщение
А если это не надо, то для "простых" лучше - Python.
Что лучше зависит от задачи. В случае питона придется ставить интерпретатор, т. к. компилятора нет.

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
А PureBasic это # отстой.
Где весомые аргументы? Так что любой ЯП написать можно. Но без аргументов высказывание не имеет смылса.

0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
16.04.2019, 16:03 18
Цитата Сообщение от locm Посмотреть сообщение
Проги с рантаймом верят несколько десятков метров. В винде по умолчанию рантайма для Qt нет.
Что в наше время пара десятка метров?

Добавлено через 1 минуту
Цитата Сообщение от locm Посмотреть сообщение
Нестандартный в том смысле что отличается от текущей темы ОС. Выглядит по другому. Я об этом написал.
Я бы не сказал что прям сильно отличается. Что Вам не нравится?

Добавлено через 2 минуты
Цитата Сообщение от locm Посмотреть сообщение
Что лучше зависит от задачи. В случае питона придется ставить интерпретатор, т. к. компилятора нет.
Правильно путь - да ставить интерпретатор.
Компилятора нет, но есть сборщики/упаковщики.

Добавлено через 46 секунд
Цитата Сообщение от locm Посмотреть сообщение
Где весомые аргументы? Так что любой ЯП написать можно. Но без аргументов высказывание не имеет смылса.
Можно писать на любом ЯП. Это да. Но стоит писать на "любом"? Стоит писать на том что удобно и нормально.
0
locm
16.04.2019, 16:14
  #19

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Что в наше время пара десятка метров?
Для простой проги это много.

Цитата Сообщение от Avazart Посмотреть сообщение
Я бы не сказал что прям сильно отличается. Что Вам не нравится?
Дело не в том нравится или нет. Выглядит как "белая ворона" по сравнению с остальными программами, у которых GUI соответствует теме ОС.

Цитата Сообщение от Avazart Посмотреть сообщение
Стоит писать на том что удобно и нормально.
Чем код выше не понравился? Он сложный? Его написать проще и быстрее чем код в первом сообщении и вдобавок он кроссплатформенный. Единственное что на разных платформах имя COM порта будет отличаться.

0
Avazart
Эксперт С++
7822 / 5720 / 563
Регистрация: 10.12.2010
Сообщений: 26,142
Записей в блоге: 17
16.04.2019, 16:24 20
Цитата Сообщение от locm Посмотреть сообщение
Для простой проги это много.
Я не думаю что это много для программы с нормальным GUI. Я уже не говорю о кроссплатформенности.

Добавлено через 1 минуту
Цитата Сообщение от locm Посмотреть сообщение
Дело не в том нравится или нет. Выглядит как "белая ворона" по сравнению с остальными программами, у которых GUI соответствует теме ОС.
Выглядит как стандартная тема. По крайней мере по Win7 при стандартной теме я не вижу отличий.

Добавлено через 59 секунд
Цитата Сообщение от locm Посмотреть сообщение
Чем код выше не понравился? Он сложный? Его написать проще и быстрее чем код в первом сообщении и вдобавок он кроссплатформенный. Единственное что на разных платформах имя COM порта будет отличаться.
Кроме того что это бейсик?
0
16.04.2019, 16:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.04.2019, 16:24

Отправка данных через COM-порт
Добрый день. Знаю что эта тема 1000 раз обсуждалась и есть куча тем ,но я не смогла найти то что...

Отправка запроса на прибор через сом-порт
Имеется прибор, который пишет наклоны, т.е. наклономер. Он выдает результаты по запросу. Есть...

Отправка СМС через COM порт на веб сервере
Пишется ком-объект для использования на вебсервере. Установлен модем, на КОМ порт(через...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru