0
votes

I am developing a utility program in C# to tune parameters of a Arduino Mega being used as a Motor controller for up to 3 motors. The data must be received by the motor controller eg. as [D2100] [=start byte, D=parameter to modify, 2=is a multiplier of 256 (0-3), 100=the remainder added to the result of the multiplication(0-255) which must remain < 1024, ]= end byte. The numeric values are passed as the Decimal ASCII value(48-51).

I have tried to send as a string via Serial.write which works when requesting data from controller as I can fill the current fields. I have sent the modified values it as a Byte by Byte from a byte Array, used convert.ToInt32 but can only seem to send as the ASCII decimal values which I have confirmed in the Arduino IDE serial window by serial.print the fields value. Having only done database programming in C back in the 1990's please excuse my ignorance I am only learning. Below is my latest version sending as a string but the butchered version of public bool ExCmd(string cmd) was used when doing the byte array and then commented out sections for the string. Been trying to resolve for two weeks, reading and coding but no resolve, any help would be greatly appreciated.

private void SlKp_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {

            if (!initLoad)
            {
                string cmdChar = "";
                int val = Convert.ToInt32(slKp.Value);
                if (enaMotor == 1)
                {
                    cmdChar = "D";
                }
                if (enaMotor == 2)
                {
                    cmdChar = "E";
                }
                if (enaMotor == 3)
                {
                    cmdChar = "F";
                }
                string val1 = Convert.ToString(val / 256);
                string val2 = Convert.ToString(val % 256);
                string cmd = '['+ cmdChar + val1 + val2 +']' ;
                if (spHandler.ExCmd(cmd))
                {
                    fieldChanged = true;
                    btSave.IsEnabled = true;
                }
            }

        }
   public bool ExCmd(string cmd)
        {
            try
            {
                if (_serialPort != null && _serialPort.IsOpen)
                {
                    _serialPort.DiscardOutBuffer();
                    _serialPort.DiscardInBuffer();
                    _receiveNow.Reset();

                    /*int intCount = 0;
                    int intChar = cmd[intCount];
                    if (intChar == 0b1011011)  //91 [ bracket is start byte
                    {                      
                        do
                        {*/
                            _serialPort.Write(cmd); //intCount,1);
                         /*   if (cmd[intCount] != 0b1011101)
                            {
                                intCount++;
                            }

                        } while (cmd[intCount] != 0b1011101 && intCount < 4); //93 ] backet is end byte
                        if(cmd[intCount] == 0b1011101)
                        {*/
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }/*
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }*/
            catch
            {
                return false;
            }
        }

Arduino Code

       case 'D':
#ifdef MOTOR_1           
            Mtr1.lKp_x100=(RxBuffer[1]*256)+RxBuffer[2];
#endif
1
"The numeric values are passed as the Decimal ASCII value(48-51)" This is clear to me for the first digit, in your example [D2100] . But not sure about the remainder 100. Is this a decimal one hundred, and transmitted as three bytes '1' , '0' , '0' . The whole number has a value of 2*256+100 = 612? Please clarify.datafiddler
@datafiddler I tried writing to the arduino as a string and yes it did send 100 as three separate bytes but I have tried as bytes and different castings and numerous different ways which I would read about and try but it all seems to get to the arduino as the Ascii code value, which from the last write I had to the Arduino was the number one (1) which should be [D01] but gets turned into 48 * 256 + 49 =12337. When it gets to the arduino it is parsed into a int[4] array so passing as a string will not work anyway causing an out of range exemption.Dave P
The base of any decoding ascii character to number is x - '0' (Identical but harder to read than x-48)datafiddler

1 Answers

0
votes

Lose the Convert.ToString() calls and just cast. If you cast to char you can continue to use the string concatenation code, but the serial port may still misinterpret it.

What you really want when dealing with binary data is a byte array. That's the native data structure that a serial port reads and writes. All the string convenience functions are assuming Unicode with a particular encoding, which only has meaning for text.


It's also good to make friends with the bitwise operations if you are going to be doing binary communications. For example, (val / 256) will do sign-extension if the number is negative, messing up your data stream. What you want is (byte)(val >> 8).