Hi everybody !
The purpose is to manage serial communication between a pedal and the computer.
I begin to search for the serial port on which the pedal is connected :
- I request the sotware version of the pedal
- I set up a timer of 20 ms to escape if no reply
- I set up the mode
- I set up again the timer of 20 ms
- If OK I set up a new timer of 200 ms to request the pedal state
This runs fine.
Here is the main :
At the present time the method enumerate_pedal() sets up a new timer of 2s just to display a warning message.Code:int _tmain(int argc, _TCHAR* argv[]) { pedal My_Pedal; My_Pedal.enumerate_pedal(); if (My_Pedal.search_pedal_port()) My_Pedal.activate_pedal(); std::cin >> key; My_Pedal.deactivate_pedal(); return 0; }
Here is the header of the pedal class :
And the cpp of the class pedal :Code:#pragma once #include <string> #include "toolbox.h" #include "template_timer.h" #include "const_pedal.h" #include "tserial_event.h" #include "enumser.h" class pedal { public: void enumerate_pedal(void); void activate_pedal(void); bool search_pedal_port(void); void deactivate_pedal(void); static char* reply_iss_version; static char* reply_serial_number; static char* reply_configuration; static char* reply_io_state; // state comes with UP or DOWN static bool pedal_state; private: void wait_for_reply(void); void OnTimedEvent_PedalReply(void); void OnTimedEvent_PedalRequest(void); void OnTimedEvent_PedalEnumeration(void); // the callback function has to be a static one if any class member ! static void SerialEventManager(uint32 object, uint32 event); static void OnDataArrival(int size, char *buffer); static void todo_on_pedalchange(void); void request_iss_version(void); void request_pedal_state(void); void request_serial_number(void); void configure_io_mode(void); TTimer<pedal> timer_pedal_enumeration; TTimer<pedal> timer_pedal_request; TTimer<pedal> timer_pedal_reply; static char* serial_number; static std::string firmware_revision_number; // status comes with OK or not static bool pedal_status; static bool iss_version_received; static bool io_mode_received; static bool pedal_state_received; static bool pedal_state_mem; static bool first_pedalrequest; bool pedalreply_timeelapsed; };
The purpose now is to make it running after the pedal being disconnected and connected again.Code:#include "stdafx.h" #include "pedal.h" #include <sstream> tserial_event* com; int error; CSimpleArray<UINT> ports; CSimpleArray<CString> friendlyNames; CSimpleArray<CString> sPorts; int port_number; char* pedalport = PEDALPORT_UNKNOWN; // ********************************************************** // * todo_on_pedalchange * // * * // * put here the stuff you have to do when a state change * // * occurs * // ********************************************************** void pedal::todo_on_pedalchange(void) { if (pedal_state) printf("Pedal ACTIVATED \n"); else printf("Pedal UNACTIVATED \n"); } // ********************************************************** // * OnDataArrival * // ********************************************************** void pedal::OnDataArrival(int size, char *buffer) { std::ostringstream oss; std::string sbuffer; int i_num; if ((size>0) && (buffer!=0)) { buffer[size] = 0; sbuffer = buffer; #ifdef DISPLAY_ONDATA_ARRIVAL printf("OnDataArrival: %s ",buffer); printf("\n"); #endif switch (size) { case 1 : reply_io_state = buffer; // pedal is linked to the first IO input i_num = int(buffer[0]) & 1; pedal_state = (i_num == 0); if (first_pedalrequest) { pedal_state_mem = pedal_state; first_pedalrequest = false; } else { if (pedal_state != pedal_state_mem) { pedal_state_mem = pedal_state; todo_on_pedalchange(); } } pedal_state_received = true; break; case 2 : reply_configuration = buffer; // converting to ascii i_num = int(buffer[0]); if (i_num < 0) i_num = i_num + 256; pedal_status = (i_num == 0xff); io_mode_received = true; break; case 3 : reply_iss_version = buffer; i_num = buffer[1]; oss << i_num; firmware_revision_number = oss.str(); iss_version_received = true; break; case 8 : reply_serial_number = buffer; serial_number = reply_serial_number; break; } } } // ********************************************************** // * SerialEventManager * // ********************************************************** void pedal::SerialEventManager(uint32 object, uint32 event) { char *buffer; int size; tserial_event *com; com = (tserial_event *) object; if (com!=0) { switch(event) { case SERIAL_CONNECTED : #ifdef DISPLAY_CONNECTED printf("Connected ! \n"); #endif break; case SERIAL_DISCONNECTED : #ifdef DISPLAY_DISCONNECTED printf("Disonnected ! \n"); #endif break; case SERIAL_DATA_SENT : #ifdef DISPLAY_DATA_SENT printf("Data sent ! \n"); #endif break; case SERIAL_RING : #ifdef DISPLAY_DRING printf("DRING ! \n"); #endif break; case SERIAL_CD_ON : #ifdef DISPLAY_CARRIER_DETECTED printf("Carrier Detected ! \n"); #endif break; case SERIAL_CD_OFF : #ifdef DISPLAY_NO_MORE_CARRIER printf("No more carrier ! \n"); #endif break; case SERIAL_DATA_ARRIVAL : size = com->getDataInSize(); buffer = com->getDataInBuffer(); OnDataArrival(size, buffer); com->dataHasBeenRead(); break; } } } // ********************************************************** // * enumerate_serial_ports * // ********************************************************** bool enumerate_serial_ports(void) { //Initialize COM (Required by CEnumerateSerial::UsingWMI) CoInitialize(NULL); //Initialize COM security (Required by CEnumerateSerial::UsingWMI) HRESULT hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if (FAILED(hr)) { printf("Failed to initialize COM security, Error:%x\n", hr); CoUninitialize(); return false; } #if defined CENUMERATESERIAL_USE_STL std::vector<UINT> ports; #if defined _UNICODE std::vector<std::wstring> friendlyNames; std::vector<std::wstring> sPorts; #else std::vector<std::string> friendlyNames; std::vector<std::string> sPorts; #endif size_t i; #elif defined _AFX CUIntArray ports; CStringArray friendlyNames; CStringArray sPorts; INT_PTR i; #else /* CSimpleArray<UINT> ports; CSimpleArray<CString> friendlyNames; CSimpleArray<CString> sPorts; int i; */ #endif ///////////////////////// Serial Ports Enumeration Methods //////////////////////////////////////////// // CREATEFILE_SERIAL_ENUMERATION_METHOD #ifdef CREATEFILE_SERIAL_ENUMERATION_METHOD printf(CREATEFILE); if (CEnumerateSerial::UsingCreateFile(ports)) goto Co_Uninitialize; else { printf(CREATEFILE_FAILURE, GetLastError()); return false; } #endif // QUERY_DOSDEVICE_SERIAL_ENUMERATION_METHOD #ifdef QUERY_DOSDEVICE_SERIAL_ENUMERATION_METHOD printf(QUERY_DOSDEVICE); if (CEnumerateSerial::UsingQueryDosDevice(ports)) goto Co_Uninitialize; else { printf(QUERY_DOSDEVICE_FAILURE, GetLastError()); return false; } #endif // GET_DEDAULT_COMMCONFIG_SERIAL_ENUYMERATION_METHOD #ifdef GET_DEDAULT_COMMCONFIG_SERIAL_ENUYMERATION_METHOD printf(GET_DEFAULT_COMMCONFIG); if (CEnumerateSerial::UsingGetDefaultCommConfig(ports)) goto Co_Uninitialize; else { printf(GET_DEFAULT_COMMCONFIG_FAILURE, GetLastError()); return false; } #endif // GUID_DEVINTERFACE_SERIAL_ENUMERATION_METHOD // buggy on Windows 7 Professional #ifdef GUID_DEVINTERFACE_SERIAL_ENUMERATION_METHOD // Issue while testing on Windows 7 Professional printf(GUID_DEVINTERFACE); if (CEnumerateSerial::UsingSetupAPI1(ports, friendlyNames)) goto Co_Uninitialize; else { printf(GUID_DEVINTERFACE_FAILURE, GetLastError()); return false; } #endif // PORTS_DEVICE_INFORMATION_SERIAL_ENUMERATION_METHOD #ifdef PORTS_DEVICE_INFORMATION_SERIAL_ENUMERATION_METHOD printf(PORT_DEVICE_INFORMATION); if (CEnumerateSerial::UsingSetupAPI2(ports, friendlyNames)) goto Co_Uninitialize; else { printf(PORT_DEVICE_INFORMATION_FAILURE, GetLastError()); return false; } #endif // ENUMPORTS_SERIAL_ENUMERATION_METHOD // buggy on Windows 7 Professional #ifdef ENUMPORTS_SERIAL_ENUMERATION_METHOD printf(ENUMPORTS); if (CEnumerateSerial::UsingEnumPorts(ports)) goto Co_Uninitialize; else { printf(ENUMPORTS_FAILURE, GetLastError()); return false; } #endif // WMI_SERIAL_ENUMERATION_METHOD #ifdef WMI_SERIAL_ENUMERATION_METHOD printf(WMI); if (CEnumerateSerial::UsingWMI(ports, friendlyNames)) goto Co_Uninitialize; else { printf(WMI_FAILURE, GetLastError()); return false; } #endif // COM08_SERIAL_ENUMERATION_METHOD // buggy on Windows 7 Professional #ifdef COM08_SERIAL_ENUMERATION_METHOD printf(COM08); if (CEnumerateSerial::UsingComDB(ports)) goto Co_Uninitialize; else { printf(COM08_FAILURE), GetLastError(); return false; } #endif // REGISTRY_SERIAL_ENUMERATION_METHOD #ifdef REGISTRY_SERIAL_ENUMERATION_METHOD printf(REGISTRY); if (CEnumerateSerial::UsingRegistry(sPorts)) goto Co_Uninitialize; else { printf(REGISTRY_FAILURE, GetLastError()); return false; } #endif Co_Uninitialize: //close down COM CoUninitialize(); return true; } // ********************************************************** // * OnTimedEvent_PedalEnumeration * // ********************************************************** void pedal::OnTimedEvent_PedalEnumeration(void) { printf("Attempting pedal enumeration ...\n"); } // ********************************************************** // * OnTimedEvent_PedalRequest * // ********************************************************** void pedal::OnTimedEvent_PedalRequest(void) { #ifdef DISPLAY_READING_PEDAL_STATE printf("Reading pedal state ...\n"); #endif this->request_pedal_state(); } // ********************************************************** // * OnTimedEvent_PedalReply * // ********************************************************** void pedal::OnTimedEvent_PedalReply(void) { printf("Waiting for pedal reply ... \n"); pedalreply_timeelapsed = true; } // ********************************************************** // * enumerate_pedal * // ********************************************************** void pedal::enumerate_pedal(void) { timer_pedal_enumeration.SetTimedEvent(this,&pedal::OnTimedEvent_PedalEnumeration); timer_pedal_enumeration.Start(PEDAL_ENUMERATION_PERIOD); } // ********************************************************** // * activate_pedal * // ********************************************************** void pedal::activate_pedal(void) { timer_pedal_request.SetTimedEvent(this,&pedal::OnTimedEvent_PedalRequest); timer_pedal_request.Start(PEDAL_REQUEST_PERIOD); } // ********************************************************** // * wait_for_reply * // ********************************************************** void pedal::wait_for_reply(void) { this->pedalreply_timeelapsed = false; timer_pedal_reply.SetTimedEvent(this,&pedal::OnTimedEvent_PedalReply); timer_pedal_reply.Start(PEDAL_REPLY_PERIOD,NOT_IMMEDIATELY,ONCE); } // ********************************************************** // * request_iss_version * // ********************************************************** void pedal::request_iss_version(void) { iss_version_received = false; com->sendData(ISS_VERSION_REQUEST,2); com->setRxSize(3); // waiting for 3 bytes } // ********************************************************** // * request_serial_number * // ********************************************************** void pedal::request_serial_number(void) { com->sendData(SERIAL_NUMBER_REQUEST,2); com->setRxSize(8); // waiting for 8 bytes } // ********************************************************** // * request_pedal_state * // ********************************************************** void pedal::request_pedal_state(void) { pedal_state_received = false; com->sendData(PEDAL_STATE_REQUEST,1); com->setRxSize(1); // waiting for 1 byte } // ********************************************************** // * configure_io_mode * // ********************************************************** void pedal::configure_io_mode(void) { pedal_status = PEDAL_NOK; com->sendData(CONFIGURE_IO_MODE,3); com->setRxSize(2); // waiting for 2 bytes } // ********************************************************** // * search_pedal_port * // * * // * enumerate the serial ports on the tablet * // * search for the one connected to the pedal * // ********************************************************** bool pedal::search_pedal_port(void) { std::string sport_number; std::string sport_name; char* cport_name; int port_number_max; if (enumerate_serial_ports()) { #ifdef CENUMERATESERIAL_USE_STL port_number_max = ports.size(); #else port_number_max = ports.GetSize(); #endif port_number = 0; while ((pedalport == PEDALPORT_UNKNOWN)&&(port_number != port_number_max)) { sport_number = to_string(ports[port_number]); sport_name = "COM" + sport_number; cport_name = const_cast<char*>(sport_name.c_str()); com = new tserial_event(); if (com!=0) { com->setManager(this->SerialEventManager); error = com->connect(cport_name, PEDAL_PORT_SPEED, SERIAL_PARITY_NONE, PEDAL_PORT_BITS, PEDAL_PORT_MODEM_EVENT); if (!error) { this->request_iss_version(); this->wait_for_reply(); while ((!iss_version_received)&&(!this->pedalreply_timeelapsed)); if (iss_version_received) { pedalport = cport_name; this->configure_io_mode(); this->wait_for_reply(); while ((!io_mode_received)&&(!this->pedalreply_timeelapsed)); if (io_mode_received) { this->request_pedal_state(); this->wait_for_reply(); while ((!pedal_state_received)&&(!this->pedalreply_timeelapsed)); return (pedal_state_received); } } else { com->disconnect(); port_number++; } } } } return PEDAL_UNDETECTED; } } // ********************************************************** // * deactivate_pedal * // ********************************************************** void pedal::deactivate_pedal(void) { timer_pedal_request.Stop(); timer_pedal_reply.Stop(); if (com != 0) com->disconnect(); }
I thought to move :
into the method enumerate_pedal. When done the timer set by wait_for_reply() doesn't seem to run again and I never go out of the first while loop of the method search_pedal_port().Code:if (My_Pedal.search_pedal_port()) My_Pedal.activate_pedal();
Note : on my PC the pedal is connected onto the second serial port, not the first one.
So I don't understand the trouble.
Many thanks.


Reply With Quote
Bookmarks