Обмен данными между компьютером и Arduino Uno через COM-порт

Доброго времени суток. Задаю данный вопрос в надежде, что кто-то с этим уже сталкивался.
Необходимо чтобы компьютер и ардуинка обменивались данными через COM-порт. Я написал программу на ардуинку и на компьютер, используя C++. Сразу после прошивки ардуино всё работает как часы, но если отключить ардуинку от COM-порта, а снова подключить, то у ардуинки уже не получается получить данные от компьютера. С чем может это быть связано?
Код для компьютера

#include <windows.h>
#include <iostream>
using namespace std;

HANDLE serial;
char outData[] = "s";
DWORD outDataSize = sizeof(outData);
DWORD outBytesWritten;

void SerialRead() {
    DWORD inputDataSize;
    char receivedChar;
    while (true) {
        ReadFile(serial, &receivedChar, 1, &inputDataSize, 0); 
        if (inputDataSize > 0) cout << receivedChar;
    }
}

int main(){
    cout << ">> begin\n";
    LPCTSTR name = L"COM4";
    DCB sParams;

    serial = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (serial == INVALID_HANDLE_VALUE){
        if (GetLastError() == ERROR_FILE_NOT_FOUND){
            cout << ">> serial port does not exist\n";
            CloseHandle(serial);
            return 0;
        }
        cout << ">> some other error occurred\n";
        CloseHandle(serial);
        return 0;
    }

    if (!GetCommState(serial, &sParams)) {
        cout << ">> getting state error\n";
        CloseHandle(serial);
        return 0;
    }
    sParams.BaudRate = CBR_9600;
    sParams.ByteSize = 8;
    sParams.StopBits = ONESTOPBIT;
    sParams.Parity = NOPARITY;
    if (!SetCommState(serial, &sParams)) {
        cout << ">> error setting serial port state\n";
        CloseHandle(serial);
        return 0;
    }

    BOOL write = WriteFile(serial, outData, outDataSize, &outBytesWritten, NULL);
    cout << write;

    cout << ">> reading\n";
    while (true) SerialRead();

    return 0;
}

Код для Arduino

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.read() == 's') Serial.print('e');
}

Связано это с тем, что компьютер теряет COM порт, а при подсоединение заново, требуется его инициализация/открытие.
Ненавижу связку устройство/компьютер по такой схеме, давно перешел на HID.
При чем, воткнув в другой USB порт, ардуинку, получите другой номер COM порта.

1 лайк

Но не работает только отправка данных с компьютера на ардуинку. Если читать данные с ардуинки на компьютер по данной связи, то всё работает, как часы.

На моём ноутбуке только один порт USB, через который я подключаюсь к ардуинке

Так у вас комп один раз в начале, передаёт два символа, а затем тоже в режиме приёма. Что ардуинка может получить от приёмника?

Не отключай. Поставь там и там HC-12 и всё

После прошивки ардуинки я включаю свою программу на C++, она корректно отправляет букву, которую успешно получает ардуинка, и читает потом букву, которую отправляет уже сама ардуинка. Всё хорошо работает.
НО если отключить ардуинку от COM-порта и выключить программу на компьютере, а затем вновь подключить ардуинку к COM-порту и запустить программу на C++ заново, то ничего не получается.

Спасибо, но мне нужно передать данные именно через провод

Возможно при инициализации COM порта на ПК происходит RESET Ардуино и в момент отправки от ПК, ардуино находится в RESET. Добавьте задержку в пару секунд после SetCommState для проверки этого предположения.

1 лайк

У вас сейчас всего одна отправка и прием, если программы на ардуине и ПК почему-то пропустили обмен - ничего работать не будет.
Добавьте в программу на ПК цикл, чтобы код непрерывно слал что-то в порт. Не слишком часто, скажем раз в 1 или 5 секунд, но не один-единственный раз, как сейчас

1 лайк

Установка тайм-аутов может решить проблему?

1 лайк

Установка тайм-аута и решила проблему

Типа так?

    ReadIntervalTimeout = -1;
    ReadTotalTimeoutMultiplier = -1;
    ReadTotalTimeoutConstant = 500;
    WriteTotalTimeoutMultiplier = 0;
    WriteTotalTimeoutConstant = 500;

Я использовал Sleep(3000). Всё работает

То, что работает, хорошо.
Я привёл пример инициализации COM-port на компьютере.

Почему здесь по -1?

Зачем нужны данные тайм-ауты?

У меня работает скрипт на VBA Excel, поэтому, просто сдул с какого-то форума.
Если хотите разобраться, поищите в интернете работу:
“Титов О.Работа с коммуникационными портами (COM и LPT) в программах для Win32”.

1 лайк