LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble using start and stop buttons

Hello,
 
I was wondering if someone could help me out with my porblem. Basically i am tryin to receive data through my serial port continously. I have designed an interface using lab windows using the rs232 lib to receive the data when i press the start button callback, so it reads the data n goes into my function routine which does the calculations, displays on the screen. here i hv a do while loop.....that is i want it to continouslly keep reading the serial port...do the rest of the calculation...carry on doing this until the user presses stop which is a callback function on the main interface.
 
I tried using check =GetUserEvent (0, &eventPanelID[0], &eventControl[0]);  thus in the do while loop kept checking for the check flag...if set to 1 then stop otherwise continue.....this wrk so when i press the stop buttom it stops.....but the problem with this is it skips every other string that the serial port receives....dont know why. the moment i disable that line....my code wrks fine....receives all the data that the serial port is receiveing n it updates the interface propely.
 
I would like to guided in what other way i can setup my stop button so that it stops reading the serial port when the user presses it and yet not loose data.
 
looking forward for a prompt reply.
 
Thanks
 
k1_ke
0 Kudos
Message 1 of 13
(4,822 Views)
In case of an endless while loop a good approach can be to insert inside the loop a ProcessSysteEvent ()  function that permits the system to manage user interface events like the pression of a button, otherwise all those events are ignored. By means of a global flag raised inside the callback for the Stop button you can break off the while loop and terminate your program. The loop will be as follows:
 
stopButtonFlag = 0;
while (!stopButtonFlag) {
   ProcessSystemEvents ();
   // Manage your RS232 dialogue
}
 
The stop button callback will be limited to
 
stopButtonFlag = 1
 
But there can be different approaches to manage a system like that. You could think of using an asyncronous timer to manage serial communication or spawn a different thread for it. In both cases, the main thread manages the user interface and remains free from rs232 communication management which is demanded to the other thread.


Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 13
(4,795 Views)
Hi Roberto,
 
Thank you very much for your prompt reply. I tried what you suggested, wellthe buttom wrks fine but i am still loosing data from the serial. Below are my callback function for start and stop buttons.
 
/*---------------------------------------------------------------------------*/
/* Read data from COM port                                                   */
/*---------------------------------------------------------------------------*/
int CVICALLBACK ReadCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
  {
  case EVENT_COMMIT:
   if(flag==0)    
   {
    flag=1;
    while (!StopButtonFlag)
    {
     ProcessSystemEvents ();
     ReadData();                                      //reads data from Com Port
    }
   }
   else
    flag=0;
        case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Stop receiving data from COM port                                         */
/*---------------------------------------------------------------------------*/
 int CVICALLBACK StopCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 
 switch (event)
  {
  case EVENT_COMMIT:
//   ResetTextBox (panelhandle, MAIN_TBOX_READ, "\0");
   StopButtonFlag=1;
 
  case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}
 
 
0 Kudos
Message 3 of 13
(4,790 Views)
Hi Roberto,
 
Thank you very much for your prompt reply. I tried what you suggested, wellthe buttom wrks fine but i am still loosing data from the serial. Below are my callback function for start and stop buttons.
 
/*---------------------------------------------------------------------------*/
/* Read data from COM port                                                   */
/*---------------------------------------------------------------------------*/
int CVICALLBACK ReadCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
  {
  case EVENT_COMMIT:
   if(flag==0)    
   {
    flag=1;
    while (!StopButtonFlag)
    {
     ProcessSystemEvents ();
     ReadData();                                      //reads data from Com Port
    }
   }
   else
    flag=0;
        case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Stop receiving data from COM port                                         */
/*---------------------------------------------------------------------------*/
 int CVICALLBACK StopCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 
 switch (event)
  {
  case EVENT_COMMIT:
//   ResetTextBox (panelhandle, MAIN_TBOX_READ, "\0");
   StopButtonFlag=1;
 
  case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}
 
 
0 Kudos
Message 4 of 13
(4,789 Views)
Hi Roberto,
 
Thank you very much for your prompt reply. I tried what you suggested, wellthe buttom wrks fine but i am still loosing data from the serial. Below are my callback function for start and stop buttons.
 
/*---------------------------------------------------------------------------*/
/* Read data from COM port                                                   */
/*---------------------------------------------------------------------------*/
int CVICALLBACK ReadCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
  {
  case EVENT_COMMIT:
   if(flag==0)    
   {
    flag=1;
    while (!StopButtonFlag)
    {
     ProcessSystemEvents ();
     ReadData();                                      //reads data from Com Port
    }
   }
   else
    flag=0;
        case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Stop receiving data from COM port                                         */
/*---------------------------------------------------------------------------*/
 int CVICALLBACK StopCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 
 switch (event)
  {
  case EVENT_COMMIT:
//   ResetTextBox (panelhandle, MAIN_TBOX_READ, "\0");
   StopButtonFlag=1;
  
  case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
}
 
 
0 Kudos
Message 5 of 13
(4,789 Views)
i am soo sorry about multiple previous replies. My internet went down but it kept sending replyin while i thought it wasn't. Sorry abt that. Well in the previous email i sent the start n stop callbacks....and ReadData routine is where it checks the serial port...
 
void ReadData(void)
{  
 int tbox=0;
 int i=0,tag=0;
//  ProcessSystemEvents ();
  ResetTextBox (panelhandle, MAIN_TBOX_READ, "\0");
     GetCtrlVal (panelhandle, MAIN_READ_COUNT, &read_cnt);
     GetCtrlIndex (panelhandle, MAIN_READTERM, &read_term_index);
     FlushInQ (comport);                                                                                    
    switch (read_term_index)
     {
   case 0:
         read_term = 0;
          break;
         case 1:
             read_term = 13;
             break;
         case 2:
           read_term = 10;
             break;
     }    

   do
         { 
          bytes_read = ComRdTerm (comport, read_data, read_cnt,
                                      read_term);
             CopyString (tbox_read_data, 0, read_data, 0, bytes_read);
             tbox = (int)(tbox_read_data[1] & 0x0C);
         }while(tbox !=0xC);
        
        t = GetSystemTime (&hour, &minutes, &sec); 
         printf("%s\n",tbox_read_data);
     SetCtrlVal (panelhandle, MAIN_TBOX_READ, tbox_read_data);
     RS232Error = ReturnRS232Err ();  
     if (RS232Error)
      DisplayRS232Error ();
//  check = GetUserEvent (0, &eventPanelID[0], &eventControl[0]);
}
0 Kudos
Message 6 of 13
(4,788 Views)

Hi, k1_ke. I am sorry for this late response: it's Christmas time here and I was not in the office in the previous days.

What do yuo mean with "I am still loosing data from the serial"?

Looking at your read_data function I noticed that after deciding how may characters and which termination character to wait for it enters an endless loop that exits only for a certain character in second position in the received message. You are not checking inside the loop if an error or timeot has occurred, so you may be out of sybc with your transmission without knowing it.

I would suggest you to test bytes_read value immediately after ComRdTerm and discriminate these situations:

- bytes_read < 0 => an error has occurred

- bytes_read < read_cnt => timeout during read

If you communication times out you may need to alter the timeout time with SetComTime.

Second item, as you can see in the documentation for ComReadTerm,

"If the termination byte equals a carriage return and the character immediately following the carriage return is a linefeed, then both the carriage return and linefeed are discarded.

If the termination byte equals a linefeed and the character immediately following the linefeed is a carriage return, then both the linefeed and the carriage return are discarded."

So be sure that you don't have a pair of 0xC-0xA (or 0xA-0xC) bytes in your transmission otherwise ComRdTerm is discarding a character more than you expected from the buffer this way altering the syncronization between transmitter and receiver

I hope these notes can help you to solve your problems and whish you a very good and prosperous new year

Roberto



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 7 of 13
(4,751 Views)
Hi Roberto,
 
Happy New Year to you to! Thank you very much for your reply. I was not in the office aswell.
 
Ok i made the respective changes suggested by you. I am reading the correct bytes and there is no timeout during the read so thats good! Also when i check for the tag, those 2 bits are extra and not of any use and nor do they occur inbetween the string, so the data read is the startin at all times and my termination byte is linefeed which i send through serial to be on safe side.
 
I found out where my problem is, in my readcallback, just before when i read the serial port, i hv added ProcessSystemEvents (); so that if the stop button is pressed, the receiving stops. This is messsing up my receive for some reason. For test purposes i hv added a tag like a counter after every data stream sent out....so when i check this counter i can see that every other data stream is missing, also if i make changes on the data i am sending out, it takes a while to show up on the screen. but the moment i disable ProcessSystemEvents (); it works fine except i cant terminate or stop it cos its stuck in the endless loop.
case EVENT_COMMIT:
   if(flag==0)    
   {
    flag=1;
    while (!StopButtonFlag)
    {
     ProcessSystemEvents ();
     ReadData();                                      //reads data from Com Port
    }
   }
   else
    flag=0;
        case EVENT_RIGHT_CLICK :
            break;
        }
    return 0;
Have you got any other suggestion  on how to go about the stop button. I really appreciate you helping you and hope to hear from you.
 
Thanks
 
k1_ke
0 Kudos
Message 8 of 13
(4,707 Views)

K1_ke, since your messages end with a fixed termination character that is never used inside the message, you could try to install a callback on the com port instead of using and endless loop for managing the serial communication. Using InstallComCallback (1, LWRS_RXFLAG, 0, 10, ComCallback, 0); you can install a callback on the serial port that is fired every time on the buffer a linefeed is present on the serial port. When the callback is fired, read the data on the port and manage your message as in your ReadData function, without need for do loops inside. With this architecture your UIR is never stuck in loops and you can deinstall the callback to stop serial comm. Be careful to check input queue lenght after reading since in some case the callback can be fired even if there are no more characters in the queue (there is a notice in the function help on this). Also, checking queue lenght before ending the callback can be safe in case a new message is received before the callback has ended (I don't remember if in this case the callback is fired again or not).

Another way to manage your application is to structure it in two threads, the main one that manages the user interface and spawns a second thread when serial communication is needed. The second thread can be structured in an endless loop with a global variable that manages loop break. For a reference on multithreading take a look at MultithreadingOverview.pdf document that you can find in <cvidir>\bin directory and to all documents found in the online help on multithreading.

In my opinion the com callback approach is easier to run and can be satisfactory if your communication rate is not too high (say some messages per second).

Message Edited by Roberto Bozzolo on 01-03-2006 11:11 AM



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 9 of 13
(4,680 Views)

Hi Roberto,

Thanks for your reply. I implemented the InstallComCallBack, now it works fine....i am still doing some tests to check i am not missing any data from the serial port but i have noticed that now my quit button takes a while to react. Sometimes it quick to close, other times it takes long, it just freezes for abit n closes. I dont know why. I haven't touched the Quit callback.

This is what i did

int CVICALLBACK ReadCallBack (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
 {
  case EVENT_COMMIT:
   StopButtonFlag=0;
   ResetTextBox (panelhandle, MAIN_TBOX_READ, "\0");
   SetCtrlAttribute (panelhandle, MAIN_READ, ATTR_DIMMED, 1);
   SetCtrlAttribute (panelhandle, MAIN_STOP, ATTR_DIMMED, 0);
   SetCtrlAttribute (panelhandle, MAIN_CONFIG, ATTR_DIMMED, 1);
   GetCtrlVal (panelhandle, MAIN_READ_COUNT, &read_cnt);
    GetCtrlIndex (panelhandle, MAIN_READTERM, &read_term_index);
    FlushInQ (comport);
    
     switch (read_term_index)
     {
   case 0:
         read_term = 0;
          break;
         case 1:
             read_term = 13;
             break;
         case 2:
           read_term = 10;
             break;
     }

  InstallComCallback (1, LWRS_RXFLAG, 0, read_term, ComCallback, 0); 
  case EVENT_RIGHT_CLICK :
            break;
    }
    return 0;
}

void ComCallback(int portNo, int eventMask, void *data)
{
 if(!StopButtonFlag)
 {  
  ReadData();   //reads data from Com Port  
 }
 FlushInQ (comport);
}

 
I will get back to you if i encounter any problems other than the one mentioned.
 
I would like to thank you for helping me out. It has helped me alot!
 
Thanks
 
k1_ke

Message Edited by k1_ke on 01-03-2006 01:16 PM

0 Kudos
Message 10 of 13
(4,657 Views)