How to resolve the conflicting data type in c#

Discussion in 'C' started by firstoption, Apr 1, 2014.

  1. firstoption

    firstoption New Member

    Joined:
    Apr 1, 2014
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Good day Sir,
    Please i need your help and guide on how to resolve these conflicting data types in C# and C.I need to send string data
    from my Graphic User Interface to the microcontroller which was programmed in C.Below are the lines of code.

    CODE OBJECTIVE:To use the slider(trackbar) in Visual Studio Express to vary the brightness of Leds
    C# codes
    Code:
    -----------
    /*
    private void trackBar1_Scroll(object sender, EventArgs e)
            {
                string dataToWrite;
                UInt32 numBytesWritten = 1;
                int percent = (int)(((double)trackBar1.Value / (double)trackBar1.Maximum) * 100);
                label2.Text = (percent.ToString()) + "%";
                dataToWrite = Convert.ToString(trackBar1.Value);
                if (dataToWrite == "1")
                {
                    chdata[0] = dataToWrite;
                    myFtdiDevice.Write(chdata[0], chdata[0].Length, ref numBytesWritten);
                }
                else if (dataToWrite == "2")
                {
                    chdata[1] = dataToWrite;
                    myFtdiDevice.Write(chdata[1], chdata[1].Length, ref numBytesWritten);
                }
                else if (dataToWrite == "3")
                {
                    chdata[2] = dataToWrite;
                    myFtdiDevice.Write(chdata[2], chdata[2].Length, ref numBytesWritten);
                }
                else if (dataToWrite == "4")
       */
    
     C code section
    ---------------
    
    /*
          unsigned char data;
          unsigned char data1;
          int  pwr_led1;
          char     trackvalue;
    
    
    
    
    
    data=USART_Receive();//this function receives data (through USB port) from Graphic User Interface and copy it  to thevariable named 'data'
    	
    	if(data=='a')
    	  {
    		data1=data;//Letter characters('a','b','c') are copied to the variable named 'data1'
    	  }
    	  else 
    	   {
    		 trackvalue=data;//numeric characters('1','2','10')are copied to the variable named trackvalue
    
    		
    	  }
    	  
    	  if(data1=='a')
    	  {
    		 
    		  if (led1_on==1) led1_on=0; else led1_on=1;//led1 is ON if data1 is 'a'
    		  
    		  
    	  }
    	  else 
    	  {
    		  
    		  //do nothing
    		  
    	  }
    	  
    	  if(trackvalue == 0)
    	  {
    		  pwr_led1 = 0;
    		 
    		  
    	  }
    	  else if (trackvalue = 1)
    	  {
    		  pwr_led1 = 655;
    		  
    	  }
    	  else if (trackvalue == 2)
    	  {
    		  pwr_led1 = 1311;
    		  
    	  }
    	   else if (trackvalue == 3)
    	   {
    		   pwr_led1 = 1966;
    		   
    	   }
    	    else if (trackvalue == 4)
    	    {
    		    pwr_led1 = 2621;
    		    
    	    }
               else 
    		 {
    			 pwr_led1 = 3277;
    			 
    		 }
    
    
    */
    
    MY PROBLEM
    --------------
    The code works fine when the value of TRACKVALUE varialbe is single digit numeric character:('1','2','3','4','5','6','7','8','9')
    but the code does not work from '10','11','12','13' upward.it gives conflicting response.After going through the code,i discovered that
    the data that is being sent from the Graphic User Interface(C#) is of the type 'string' while the variable 'data'in the (C section of my program)
    is defined as ' unsigned char'.These conflicting data types is what i think is responsible for the program not recognising numeric string from
    '10','11','12' upward.

    myFtdiDevice.Write(chdata[0], chdata[0].Length, ref numBytesWritten);this function accepts only string data types and it is the function that sends that to the microcontroller.


    My question is,how can i declare a variable (in the C section of my program )that can hold the numeric string that is being sent fron the GUI.I
    will highly appreciate any guide and support in this regards.My programming experience is still very limited.
    Best regards.
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Which is correct? It's not possible to answer if you don't say. A conflict can only be resolved when you know which one is correct and which one is wrong.

    If the C# code is correct and you need to be able to send character strings that are longer than one character then your microcontroller code is going to need some serious rework.

    If on the other hand the microcontroller code is correct (in that it only handles single character commands) then your C# code is wrong.

    There are some points of confusion in your C code and it's not at all clear to me if your C code is right or wrong.
    Code:
    	if(data=='a')
    	  {
    		data1=data;//Letter characters('a','b','c') are copied to the variable named 'data1'
    	  }
    
    Understand that the test is ONLY for equality with 'a'. If data is 'b' then it will not be copied to data1 by this code. If you wanted all letters between, say, 'a' and 'e' copied to data1, then you would need something like:
    Code:
    	if(data>='a' && data1<='e')
    	  {
    		data1=data;//Letter characters('a','b','c') are copied to the variable named 'data1'
    	  }
    
    Either the code or the comment is wrong here:
    Code:
    trackvalue=data;//numeric characters('1','2','10')are copied to the variable named trackvalue
    
    Understand that '10' is not valid. Single quotes are for SINGLE characters only, not character strings. If "10" is valid then this is "10", not '10', and is equivalent to {'1','0','\0'}, because C strings are terminated with a zero-byte character. Your C code would then need to parse this differently as you cannot compare strings with ==. Single quoted characters are 8-bit numeric constants and designed to make code easier to read; 'A' is equal to 65 if you're using ASCII.

    Actually, this code toggles the LED if data1 is 'a':
    Code:
    if(data1=='a')
    {
        if (led1_on==1) led1_on=0; else led1_on=1;//led1 is ON if data1 is 'a'
    }
    
    If you just want 'a' to mean "LED on" then you would need to do this:
    Code:
    if(data1=='a')
    {
        led1_on=1; //led1 is ON if data1 is 'a'
    }
    
    This is definitely wrong:
    Code:
    trackvalue=data;//numeric characters('1'...
    ...
    if (trackvalue = 1)
    
    1 is not equal to '1'. '1' is the character code of 1, which is 49 in ASCII. If you want trackvalue to contain 1 when a '1' is passed in, then you will need to subtract '0' from it:
    Code:
    if (data>='0' && data<='9')
        trackvalue=data-'0';
    
    This will set trackvalue to 0-9 for inputs '0'-'9'.


    Finally, in code like this you would be better off using switch/case instead of an if/else-if ladder:
    Code:
    switch(trackvalue)
    {
    case '0':
      // do trackvalue=0 stuff
      break;
      
    case 1:
      // do trackvalue=1 stuff
      break;
    
    //etc
    }
    
     
    shabbir likes this.
  3. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Slight error in the above post; for the switch I should have said:
    Code:
    switch(trackvalue)
    {
    case '0':
      // do trackvalue='0' stuff
      break;
      
    case '1':
      // do trackvalue='1' stuff
      break;
    
    case 2: // for demonstration
      // do trackvalue=2 stuff (note not trackvalue='2')
      break;
    
    //etc
    }
    
     
  4. firstoption

    firstoption New Member

    Joined:
    Apr 1, 2014
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Good day Sir.Thank you very much for the support and guide.I really appreciate your sense of understanding.
    Sir,my assumption is that the problem lies in the C section of my program.My reason for thinking in that line is that I can ON and OFF the Led on my Board through the data("a")sent from Graphic User Interface in C# to the microcontroller which I programmed with C.The problem starts when I begin to send two digits numbers("10","11'),but I have realized from the explainations you made why it is not possible to receive the two digits numbers in the C section of my code since C does not have string data type.However,i still have a question with respect to one of the explainations you made.you said "10" in string format is equivalent to {'1','0','\0'} in C if I get you right.Now the function I am using to send data to the microcontroller has three arguments,:
    public FTDI.FT_STATUS Write(string dataBuffer, int numBytesToWrite, ref uint numBytesWritten);
    one of the arguments namely "numBytesWritten" refers to the number of bytes actual written to the device.i had earlier assigned 2 to the argument but with your explaination I think it suppose to be 6 since each character in.NET framework is two bytes. I do not know if this can make any difference in the operation of the function that receive data from the GUI.Sir I will highly appreciate whatever assistance you can render in this regards.My programming experience is still very limited.Once again thank you for taking the pain to go through and correct my code.I am really very grateful.
    Best regards.
     
  5. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    My knowledge of .Net doesn't go to the required level of detail to answer this in full. I'm pretty sure you don't want to send UCS2 strings into the C code (unless you really want to parse UCS2 strings in that section). So I'd suggest finding a way of sending plain ASCII strings to the C code.

    /me has another look at the code...

    Hadn't paid much attention to the C# part. What. The. Heck. Seriously? You're having an if-else if ladder for every single value from 1 to trackBar1.Maximum, assigning that value (let's call it N) to the Nth location in chdata, then writing it using chdata[N].Length (which is only ever going to be 1)? If that's 255 values, then that's 255*5=1275 lines of code, all of which can be replaced with just one line:
    Code:
    myFtdiDevice.Write(dataToWrite, 1, ref numBytesWritten);
    
    You can still use this one line of code even if trackBar1.Maximum is 4. But I suspect it's not, because otherwise you wouldn't be talking about strings like "10".

    You're going to have to change the C code. Does USART_Receive() return one character at a time?
    Under what circumstances does it return 'a'?

    If it does return one character then it's not going to return the string "10" in one go. You'll have to call it more than once. But you'll also have to know how many times to call it. Then you'll have to process the results.

    What is trackBar1.Maximum? Assuming it is less than 256 (which it will have to be to fit into an unsigned char), dataToWrite.Length is going to be 1,2 or 3. One way is to prefix this to the string, i.e.:
    Code:
    dataToWrite = Convert.ToString(trackBar1.Value);
    dataToWrite = Convert.ToString(dataToWrite.Length) + dataToWrite;
    
    then in the C code the first call to USART_Receive() will give you the length of the string. You would then need to call USART_Receive() again that many times, and process the results accordingly, for example:
    Code:
    unsigned char length;
    unsigned char data;
    data=USART_Receive();
    if (data=='a')
    {
      if (led1_on==1) led1_on=0; else led1_on=1;//you don't even need data1.  Just do it here.
    }
    else if (data>='0' && data <='9')
    {
      // it's a digit, which is the length of the numeric data to follow
      length=data-'0';
      // So let's now convert the next "length" characters to a number:
      trackvalue=0;
      while (length)
      {
        trackvalue*=10;
        trackvalue+=USART_Receive()-'0'; // you might want to expand this with some error checking in case this is not a digit
        length--;
      }
    }
    else
    {
     // USART_Receive() returned something that wasn't in "a0123456789"
    }
    
    then data will contain the value that was in trackBar1.Value.

    Another way is to append a special character to indicate the end of the value, for example you could use '#', then keep reading until USART_Receive() returns '#', but I'll let you figure the code out for that one.

    I don't understand what the values 655, 1311, 1966, 2621 and 3277 have to do with anything. If these are the raw binary values for the LED brightness, then you could just rescale trackValue accordingly, or perhaps an easier way to do it at this stage would be to set trackBar1.Maximum in the C# to 3277. The code above scales to 4 digits without any changes, although trackvalue would have to be an int instead of a char.

    Also, depending on how much precision you want, it might be easier to zero-pad the percentage (i.e. int percent=...; ) and pass that in instead, so you'd be transmitting 00-99, which would always be 2 digits, so you wouldn't need to bother with variable length strings and could just call USART_Receive() twice. Or if you can't zero pad it, add 100 so that you transmit values from 100-199, then call USART_Receive() three times just discarding the first return. There are always lots of ways to do these things.
     
    Last edited: Apr 4, 2014

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice