Reputation: 380
I keep trying to write to a gantry motor via COM Serial Port in C++ and the device doesn't perform the command and returns random symbols.
This should move the gantry arm on a machine when it's working correctly and return the position of the arm through the read function and return the position of the arm. When I place a ComEventWait or whatever it doesn't stop waiting.
main.cpp
#include <iostream>
#include "../../../../Documents/Development/proteinmaker6channel/ProteinMaker/device_connection.h"
int main()
{
DeviceConnection dc = DeviceConnection();
dc.performWrite("XEXSULF");
dc.performWrite("YEXSULF");
dc.performWrite("ZEXSULF");
dc.performWrite("XEXHHLF");
dc.performWrite("YEXHHLF");
dc.performWrite("ZEXHHLF");
}
device_connection.cpp
#include "device_connection.h"
#include<windows.h>
#include<stdio.h>
#include <list>
#include <string>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <assert.h>
#include <stdio.h>
using namespace std;
DeviceConnection::DeviceConnection()
{
}
void DeviceConnection::open(std::string portName)
{
wchar_t pszPortName[10] = { 0 }; //com port id
wchar_t PortNo[20] = { 'C', 'O', 'M', '3', '\0' }; //contain friendly name
//Enter the com port id
//Open the serial com port
hComm = CreateFile(PortNo, //friendly name
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
NULL, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
{
printf_s("\nPort can't be opened");
system("pause");
return;
}
printf_s("\nPort opened");
}
void DeviceConnection::performWrite(std::string command) {
open("COM3");
setParameters();
setTimeouts();
write(command);
setCommMask();
//wait();
read();
CloseHandle(hComm);//Closing the Serial Port
system("pause");
}
bool DeviceConnection::write(std::string command){
//strcpy_s(SerialBuffer, command.c_str());
printf_s("\nwriting: %s \n", command.c_str());
//Writing data to Serial Port
bool Status = WriteFile(hComm,// Handle to the Serialport
command.c_str(), // Data to be written to the port
64, // No of bytes to write into the port
&BytesWritten, // No of bytes written to the port
NULL);
if (Status == FALSE)
{
CloseHandle(hComm);//Closing the Serial Port
printf_s("\nFailed to Write at %d " + BytesWritten + '\n');
return false;
}
printf_s("\nbytes written to the serail port: %d \n", BytesWritten);
return 1;
}
void DeviceConnection::read() {
//Read data and store in a buffer
char ReadData; //temperory Character
char Output[64] = "";
unsigned char loop = 0;
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
printf(&ReadData);
printf("\nreading(%d): %s", loop, &ReadData);
Output[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
--loop; //Get Actual length of received data
printf("\nbytes received = %s\n", Output);
//print receive data on console
//int index = 0;
//for (index = 0; index < loop; ++index)
//{
// //printf_s("%s", ReadData);
//}
}
void DeviceConnection::wait() {
//Setting WaitComm() Event
DWORD dwEventMask; // Event mask to trigger
OVERLAPPED o;
o.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
// Initialize the rest of the OVERLAPPED structure to zero.
o.Internal = 0;
o.InternalHigh = 0;
o.Offset = 0;
o.OffsetHigh = 0;
//assert(&o.hEvent);
printf_s("\nWaiting %d", BytesWritten);
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
printf_s("\nDone\n\n", Status);
if (Status == FALSE)
{
printf_s("\nError! in Setting WaitCommEvent()\n\n");
system("pause");
return;
}
}
void DeviceConnection::setCommMask() {
//print numbers of byte written to the serial port
//printf_s("\nSetting Comm Mask = %d", EV_RXCHAR);
//Setting Receive Mask
Status = SetCommMask(hComm, EV_RXCHAR);
if (Status == FALSE)
{
printf_s("\nError to in Setting CommMask\n\n");
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return;
}
}
void DeviceConnection::setParameters()
{
//Setting the Parameters for the SerialPort
params.DCBlength = sizeof(params);
Status = GetCommState(hComm, ¶ms); //retreives the current settings
if (Status == FALSE)
{
printf_s("\nError getting the Com state");
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return;
}
// Print some of the DCB structure values
_tprintf(TEXT("\nOriginal BaudRate: %d, ByteSize: %d, Parity: %d, StopBits: %d"),
params.BaudRate,
params.ByteSize,
params.Parity,
params.StopBits);
params.BaudRate = CBR_38400; //BaudRate = 9600
params.ByteSize = 8; //ByteSize = 8
params.StopBits = ONESTOPBIT; //StopBits = 1
params.Parity = NOPARITY; //Parity = None
Status = SetCommState(hComm, ¶ms);
if (Status == FALSE)
{
printf_s("\nError to Setting DCB Structure\n\n");
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return;
}
_tprintf(TEXT("\nUpdated BaudRate: %d, ByteSize: %d, Parity: %d, StopBits: %d"),
params.BaudRate,
params.ByteSize,
params.Parity,
params.StopBits);
printf_s("\nUpdated Parameters");
}
void DeviceConnection::setTimeouts() {
//Setting Timeouts
COMMTIMEOUTS timeouts = { 0 }; //Initializing timeouts structure
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
{
printf_s("\nError to Setting Time outs");
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return;
};
}
Upvotes: 0
Views: 797
Reputation: 13377
Your comment seems to imply that you want 9600, but you requested 38,400:
params.BaudRate = CBR_38400; //BaudRate = 9600
If you truly wanted/needed to communicate at 9600, but you are talking at 38400, that could be your issue. Try replacing the line with:
params.BaudRate = CBR_9600;
Garbage characters are typical when using an incorrect baud rate.
Upvotes: 2
Reputation: 3968
you have problems with buffering. I'm not fixing other errors, like not declared variables, sending objects by value or reading by values, because they aren't related to the question.
bool DeviceConnection::write(std::string command){
//strcpy_s(SerialBuffer, command.c_str());
printf_s("\nwriting: %s \n", command.c_str());
//Writing data to Serial Port
bool Status = WriteFile(hComm,// Handle to the Serialport
command.c_str(), // Data to be written to the port <----- YOU MUST USE REAL SIZE OF THE BUFFER, otherwise you will get undefined behaviour
command.length(), // No of bytes to write into the port
&BytesWritten, // No of bytes written to the port
NULL);
if (Status == FALSE)
{
CloseHandle(hComm);//Closing the Serial Port
printf_s("\nFailed to Write at %d " + BytesWritten + '\n');
return false;
}
printf_s("\nbytes written to the serail port: %d \n", BytesWritten);
return 1;
}
void DeviceConnection::read() {
//Read data and store in a buffer
char ReadData; //temperory Character
char Output[64] = "";
unsigned char loop = 0;
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
printf(ReadData); //<- PRINIT VALUE NOT POINTER
printf("\nreading(%d): %c", loop, ReadData); //<- PRINIT VALUE NOT POINTER
Output[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
// --loop; //Get Actual length of received data // <- incorrect
printf("\nbytes received = %s\n", Output);
}
I strongly recommend to read something about pointers in C/C++
Upvotes: 2