Thread: Please help with serial communication problem - Long

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    2

    Please help with serial communication problem - Long

    Hey all,

    I'd like to start by saying that I am an electrical engineering student and have therefore had very little experience with Visual C++. However, a part of my senior design project requires a simple rs232 interface in visual c++. My design partner and I have designed the hardware and software needed to implement a traction control system for an R/C car. The traction system works fine, but the other part of our project is wireless transmission of the traction status and speed of the 4 wheels of the car to a laptop the user will have with them. The wireless hardware has been designed and built and is sending the traction status and wheel speed measurements formatted in bytes in the following manner:

    0h10, traction status, 0h20, front left wheel speed, 0h30, front right wheel speed, 0h40, rear left wheel speed, 0h50, rear right wheel speed, and then back to 0h10, ...

    (where the wheels speeds are also just byte values)

    I pieced together what I could find online to write a simple windows program that would display this data using the 0h10, 0h20, ..., .. qualifiers to indicate what the next byte value received will represent (right front, left, etc).

    In the program I assume that I read 1 byte at a time from the serial buffer and immediately process it before the next byte arrives which should be very possible since we are using a baud rate of only 2400 bps. I simply set a flag using the qualifiers to indicate what the next byte of data will represent. This method seems like it should work, but Im not sure if I am actually reading 1 byte from the serial buffer corrently or not.

    The program compiles and initially displays the current vehicle wheel speeds and traction status but then fails to update these values at a usable rate. If after the program starts any wheel speed changes, the program doesn't register the change in incoming serial data for nearly a minute and a half. I tested the incoming serial data using a regular terminal program and the serial data changes instantly in response to vehicle wheel speed changes. Its as if the data on the screen is updated at a very slow rate and windows just stores all the incoming serial data until it finishes displaying what arrived earlier. I noticed using the windows task manager that the program continues to use more memory the entire time it is running which would reinforce my hypothesis that it is storing the incoming serial data, or there could be just a memory leak I am unaware of. I believe the cause of this to be related to the way I am reading the serial buffer using Cserial. Although like I said earlier, I dont have much experience with visual c++.

    I have pasted below the code I am currently using. I know some of you are experts in visual c++ that can give me a simple explanation and/or fix to my problem. I am very close, as like I said, the serial data is read and displayed correctly when the program starts, it just fails to update using the incoming data at anything other than minute or two intervals which makes no sense to me.

    Thanks for any and all suggestions.

    Jordan

    ---------------------
    Visual C++ Code
    ---------------------

    Code:
    #include <string>
    #include <cstring>
    #include <stdlib.h>
    #include <afx.h>
    #include "SerialWnd.h"
    #include "Resource.h"
    
    using namespace std;
    
    HDC hdc ;
    DCB dcb;
    HANDLE hCom;
    char buff[2];
    char buffout[2];
    
    HDC MemDCExercising;
    PAINTSTRUCT Ps;
    HBITMAP bmpExercising;
    HINSTANCE hInst;
    
    BOOL fSuccess;
    unsigned long dwBytesRead = 0;
    BYTE  abBuffer[100];
    
    char *pcCommPort = "COM1";
    DWORD dwCommEvent;
    DWORD dwMask;
    DWORD inqueue;
    DWORD outqueue;
    
    int TractionData=0;
    int WLF=0;
    int WLR=0;
    int WRF=0;
    int WRR=0;
    
    char fleft[26] = "Front Left Wheel Speed:  ";
    char fright[27] = "Front Right Wheel Speed:  ";
    char rleft[25] = "Rear Left Wheel Speed:  ";
    char rright[26] = "Rear Right Wheel Speed:  ";
    
    char tstatus[19] = "Traction Status:  ";
    
    CSerialWnd serial;
    
    LRESULT CALLBACK Handler(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam){
    
    if (iMsg == WM_PAINT)
    
    	{
    
    	hdc = BeginPaint(hWnd, &Ps);
    	// Load the bitmap from the resource
    	bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
    	// Create a memory device compatible with the above DC variable
    	MemDCExercising = CreateCompatibleDC(hdc);
                    // Select the new bitmap
                    SelectObject(MemDCExercising, bmpExercising);
    	// Copy the bits from the memory DC into the current dc
    	BitBlt(hdc, 0, 0, 782, 522, MemDCExercising, 0, 0, SRCCOPY);
    	// Restore the old bitmap
    	DeleteDC(MemDCExercising);
    	DeleteObject(bmpExercising);
    	EndPaint(hWnd, &Ps);
    
    	hdc = GetDC(hWnd);
    	SetTextColor(hdc, RGB(0,0,0));
    	//SetBkColor(hdc, RGB(0,0,0));
    
    	TextOut(hdc,385,435,fleft,26);
    	TextOut(hdc,5,175,fright,27);
    	TextOut(hdc,600,350,rleft,25);
    	TextOut(hdc,190,100,rright,26);
    
    	TextOut(hdc,330,30,tstatus,19);
    
    	}
    
    	
    if (iMsg == CSerialWnd::mg_nDefaultComMsg)
    	
    {
           // A serial message occurred
           const CSerialWnd::EEvent eEvent = CSerialWnd::EEvent(LOWORD(wParam));
           const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam));
    
           switch (eEvent)
           {
           case CSerialWnd::EEventRecv:
    
    			hdc = GetDC(hWnd);
    			SetTextColor(hdc, RGB(0,0,0));
    			SetBkColor(hdc, RGB(0,0,0));
    			
    			serial.Read(abBuffer,1,&dwBytesRead,0,INFINITE);
    				
    			sprintf(buffout,"%X",(LPCTSTR)abBuffer[0]);
    			SetTextColor(hdc, RGB(255,255,255));
    			//TextOut(hdc,0,80,buffout,2);
    			
                                                    // Sets flags based on qualifiers
    
    			if ((buffout[0] == '1') && (buffout[1] == '0')) {
    			
                                                    TractionData = 1;
    			break;
    
    				}
    
    			if ((buffout[0] == '2') && (buffout[1] == '0')) {
    			WLF = 1;
    			break;
    				
    				}
    
    			if ((buffout[0] == '3') && (buffout[1] == '0')) {
    			WLR = 1;
    			break;
    
    				}
    
    		                if ((buffout[0] == '4') && (buffout[1] == '0')) {
    			WRF = 1;
    			break;
    
    				}
    
    
    			if ((buffout[0] == '5') && (buffout[1] == '0')) {
    			WRR = 1;
    			break;
    
    				}
    
                                                   // Displays data based on flags
    
    			if (TractionData == 1) {
    					
    			SetTextColor(hdc, RGB(0,0,0));
    			SetBkColor(hdc, RGB(255,255,255));
    			TextOut(hdc,434,30,buffout,1);
    			TractionData = 0;
    			break;
    					
    				}
    
    		                if (WLF == 1) {
    					
    			SetTextColor(hdc, RGB(0,0,0));
    			SetBkColor(hdc, RGB(255,255,255));
    			TextOut(hdc,547,435,buffout,2);
    			WLF = 0;
    			break;
    					
    				}
    
    		               if (WLR == 1) {
    					
    		              SetTextColor(hdc, RGB(0,0,0));
    		              SetBkColor(hdc, RGB(255,255,255));
    		              TextOut(hdc,756,350,buffout,2);
    		              WLR = 0;
    		              break;
    					
    				}
    
    		              if (WRF == 1) {
    					
    		              SetTextColor(hdc, RGB(0,0,0));
    		              SetBkColor(hdc, RGB(255,255,255));
    		              TextOut(hdc,177,175,buffout,2);
    		              WRF = 0;
    		              break;
    					
    				}
    
    		              if (WRR == 1) {
    					
    		              SetTextColor(hdc, RGB(0,0,0));
    		              SetBkColor(hdc, RGB(255,255,255));
    		              TextOut(hdc,360,100,buffout,2);
    		              WRR = 0;
    		              break;
    					
    				}	
    		   
    		   break;
             
           }
             
           return 0;
       }
    
    if (iMsg == WM_DESTROY) {
    
    	PostQuitMessage(0);
    	return 0;
    	}
    
    return DefWindowProc(hWnd, iMsg, wParam, lParam);
    
    }
    
    int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow){
    
    //Declare variables
    const char* szAppName = "MyWin";
    WNDCLASSEX wndclass;
    HWND hWnd;
    MSG msg;
    
    hInst = hInstance; 
    
    wndclass.cbSize = sizeof(wndclass);			
    wndclass.style = CS_HREDRAW | CS_VREDRAW;   
    wndclass.lpfnWndProc = Handler;
    wndclass.cbClsExtra = 0;			
    wndclass.cbWndExtra = 0;						
    wndclass.hInstance = hInstance;			
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);			
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL;		
    wndclass.lpszClassName = szAppName;			
    wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 
    RegisterClassEx(&wndclass);					
    hWnd = CreateWindow(szAppName, "Wireless Telemetry Monitor", WS_OVERLAPPEDWINDOW,0,0, 782, 522, NULL, NULL, hInstance, NULL);	
    ShowWindow(hWnd, iCmdShow);					
    UpdateWindow(hWnd);							
    
    serial.Open(pcCommPort, hWnd, WM_NULL, 0, inqueue, outqueue);
    serial.Setup(CSerial::EBaud2400,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);
    serial.SetupHandshaking(CSerial::EHandshakeOff);
    
    serial.SetMask(CSerial::EEventRecv);
    serial.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking); 
    
    
    while (GetMessage(&msg, NULL,0,0)){
    				
    TranslateMessage(&msg);				
    DispatchMessage(&msg);						
    
    
    }
    return msg.wParam;						
    }

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    I just looked at the code to paint the window. Maybe it is not updating the screen frequently enough (or correctly)

    Try something like....


    Code:
    //declare static vars to hold HDC and bmp thru life of app
    static HDC		MemDCExercising=NULL;
    static HBITMAP  hbmpOld=NULL,bmpExercising=NULL,hbmpBuffer=NULL;
    
    if(iMsg == WM_CREATE) // or WM_INITDIALOG  // create the GDI when app opens
    {
    	//find size of window or fill with known values
    	RECT	ClientRect;
    	GetClientRect(hWnd,&ClientRect);//NOTE check the window is the right size when this msg is processed (may start minimised)
    
    	
    	HDC hdc=GetDC(NULL);//get display DC
    	// Create a memory device compatible with the above DC variable
    	MemDCExercising = CreateCompatibleDC(hdc);
    	// Create the new bitmap
    	hbmpBuffer=CreateCompatibleBitmap(hdc,ClientRect.right-ClientRect.left,ClientRect.bottom-ClientRect.top);
    	//Catch old BMP
    	hbmpOld=SelectObject(MemDCExercising, hbmpBuffer);
    	// Copy the bits from the memory DC into the buffer dc
    	//NOTE put this in a seperate function
    	bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
    	hBrush = CreatePatternBrush(bmpExercising);
    	FillRect(MemDCExercising,&ClientRect,&hBrush);//will 'tile' the area with image
    	//clean up GDI 
    	DeleteObject(hBrush);//not selected into a DC so can just delete
    	DeleteObject(bmpExercising);//not selected into a DC so can just delete
    	ReleaseDC(hdc);//used get so release not delete
    
                    return 0;/show we processed msg
    }
    if(iMsg==WM_CLOSE)//kill the GDI resources when app closes
    {
    	// Restore the old bitmap (this is not strictly needed if using MSVC .NET ie newer than v6)
    	SelectObject(MemDCExercising,hbmpOld);//return original bmp to avoid GDI mem leak if DC fails to delete in non original state
    	//clean up GDI
    	DeleteObject(hbmpBuffer);
    	DeleteDC(MemDCExercising);
    
                     return 0;/show we processed msg
    }
    if (iMsg == WM_PAINT)
    {
    	//make this simple and fast
    	hdc = BeginPaint(hWnd, &Ps);
    	// Copy the bits from the memory DC into the current dc
    	BitBlt(hdc, Ps.rcPaint.left, Ps.rcPaint.top, Ps.rcPaint.right-Ps.rcPaint.left, Ps.rcPaint.bottom-Ps.rcPaint.top, MemDCExercising, 0, 0, SRCCOPY);
    	EndPaint(hWnd, &Ps);
    
                    return 0;/show we processed msg
    }
    if (iMsg == CSerialWnd::mg_nDefaultComMsg)
    {
    	// A serial message occurred
    	const CSerialWnd::EEvent eEvent = CSerialWnd::EEvent(LOWORD(wParam));
    	const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam));
    
    	switch (eEvent)
    	{
    	case CSerialWnd::EEventRecv:
    		//fill the area with the tile again to overwrite the last text
    		//NOTE put this in a seperate function so easy to call
    		bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
    		hBrush = CreatePatternBrush(bmpExercising);
    		FillRect(MemDCExercising,&ClientRect,&hBrush);//will 'tile' the area with image
    		//clean up GDI 
    		DeleteObject(hBrush);//not selected into a DC so can just delete
    		DeleteObject(bmpExercising);//not selected into a DC so can just delete
    
    		//draw text to the buffer DC, MemDCExercising, as per your code
    
    	}
    	//ask for paint
    	RECT   Rect=GetClientRect(hWnd,&Rect);//paint whole window
    	//send paint msg
    	InvalidateRect(hWnd,&Rect,FALSE);
    	//send directly to app msg que (not OS que)
    	UpdateWindow(hWnd);
    
                     return 0;
    }
    else
    {
                   //we did not handle msg so send to default proccessing
                   return DefWindowProc(hWnd,iMsg,wParam,lParam);
    }
    Typically we use a switch(iMsg) { case WM_.....: break;} rather than the 'if's
    Last edited by novacain; 04-06-2005 at 12:12 AM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Feb 2002
    Posts
    329
    You also could try to decrease the inbuffer size for the port.

  4. #4
    Registered User
    Join Date
    Apr 2005
    Posts
    2
    Thank you both for your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inserting a swf file in a windows application
    By face_master in forum Windows Programming
    Replies: 12
    Last Post: 05-03-2009, 11:29 AM
  2. Serial Communication
    By Korn1699 in forum C# Programming
    Replies: 0
    Last Post: 11-29-2005, 12:50 PM
  3. Merge and Heap..which is really faster
    By silicon in forum C++ Programming
    Replies: 2
    Last Post: 05-10-2005, 04:06 PM
  4. Peculiar Problem with Printf
    By Unregistered in forum C++ Programming
    Replies: 5
    Last Post: 07-02-2002, 12:34 AM
  5. Peculiar Problem with Printf
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 07-02-2002, 12:03 AM