0
votes

I'm currently working on a master/slave where the Master is a C# program and the Slave is an Arduino Uno. The Arduino is reading several values and is working as expected, but I'm having some troubles on the C# side. I'm reading 3 bytes from an AD converter (AD7680), which returns 3 bytes of data structured in the following way:

0000 | 16 bit number | 0000

My C# program is reading the returned value in a double, which is the expected value. BUT I didn't find out how to get rid of the last four 0's and obtain the 2 byte number I need.

What should be the best approach to get the right value without loosing data? I tried 'BitConverter' but it´s not what I'm expecting, and I have no clue how to proceed. I currently can´t attach the code unfortunately, but I could reference anything on it if needed.

Thanks for reading!

EDIT: This is the function on the C# side:

public double result(byte[] command)    
    {
        try
        {
            byte[] buffer = command;
            arduinoBoard.Open();
            arduinoBoard.Write(buffer, 0, 3);
            int intReturnASCII = 0;
            char charReturnValue = (Char)intReturnASCII;
            Thread.Sleep(200);
            int count = arduinoBoard.BytesToRead;
            double returnResult = 0;
            string returnMessage = "";
            while (count > 0)
            {
                intReturnASCII = arduinoBoard.ReadByte();
                //string str = char.ConvertFromUtf32(intReturnASCII);

                returnMessage = returnMessage + Convert.ToChar(intReturnASCII);

                count--;
            }

            returnResult = double.Parse(returnMessage, System.Globalization.CultureInfo.InvariantCulture);
            arduinoBoard.Close();
            return returnResult;
        }
        catch (Exception e)
        {
            return 0;
        }

    }

And the Arduino function that communicates with it is this one:

unsigned long ReturnPressure(){
long lBuffer = 0;
byte rtnVal[3];
digitalWrite(SLAVESELECT , LOW);
delayMicroseconds(1);

rtnVal[0] = SPI.transfer(0x00);
delayMicroseconds(1);
rtnVal[1] = SPI.transfer(0x00);
delayMicroseconds(1);
rtnVal[2] = SPI.transfer(0x00);
delayMicroseconds(1);
digitalWrite(SLAVESELECT, HIGH);
// assemble into long type
lBuffer = lBuffer | rtnVal[0];
lBuffer = lBuffer << 8;
lBuffer = lBuffer | rtnVal[1];
lBuffer = lBuffer << 8;
lBuffer = lBuffer | rtnVal[2];

return lBuffer;
}
1
Please show how you receive the data from the arduino in your C# code ... is it serial?Fruchtzwerg
In a double? How can you read that in a double? Use a byte array to store the three bytes, then put them in a 32 bit int and in the end shift the value. And, most important, Please show how you receive the data from the arduino in your C# codefrarugi87
@Fruchtzwerg It is serial communication yes... I edited the main question with the asked code. I'm using double in the C# side because that function is also calling Arduino for other parameters that are being read from different sensors, and therefore I need the numerical value they read. I could create a new function for it as well, but I was trying to make this one work to simplify the things. Thanks for the support!user2783511

1 Answers

0
votes

Okay, you have to do a few steps:

Firstly: Its much easier to save the bytes in an array like this:

byte Received = new byte[3];
for(int i = 0; i < 3; i++)
{
  Received[i] = (byte)arduinoBoard.ReadByte();
}

After received the three bytes, shift it together (check if the three bytes are in the right order: Most significant byte is here at index 0)

UInt64 Shifted = (UInt64)(Received[0] << 16) | (UInt64)(Received[1] << 8) | (UInt64)(Received[0])

Now shift out the four ending zeros:

UInt64 Shifted = Shifted >> 4;

To find out, what your voltage is, you have to know the scale of your converter. The Data sheet says, "The LSB size is VDD/65536". You could define a constant

const double VDD = 5; //For example 5V

After that you can calculate your needed double with

return Shifted * (VDD / 65539); //Your voltage

Hope this helps.