FEZ Panda 2 and Resol V-Bus

Hi everyone!

Recently i ordered a FEZ Panda 2 Ultimate Kit and i’m absolutely faszinated in programming it via C#. Thanks GHI, for that lovely device.

We have installed a solar powered water heating from RESOL and i want to read and write from/to the proprietary bus from RESOL named V-Bus (http://resol-vbus.googlegroups.com/web/VBus-Protokollspezifikation.pdf?gda=Rqd501IAAACxaNUYKzNHxGTfDLrbwoEU9h30bCGztnlCV21Bjjbsi-ucwbKl-bCwnZ77JemedPPCej_KYKUgNufNa4qtEk7oVeLt2muIgCMmECKmxvZ2j4IeqPHHCwbz-gobneSjMyE - sorry i found that only in german).
This 2-wire bus is low at 8,2V and hi on ground - 9600-8N1, no handshake.

Could you suggest me a way to get a bidiretional connection with the Panda?

Thanks in advance for any help,
mark

This is just serial connection I assume so you only need the serial drivers on FEZ.

The voltage levels can be easily take c care of using some transistors. Take a look at FEZ Mini schematics for example

Thanks Gus,

i finally did it with a schematic i found here VBus-Decoder – Hobbyelektronik.org


    class VBUS
    {
        // for testing: static byte[] VALUE = new byte[] { 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D };

        private static byte CRC(ref byte[] Buffer, int Offset, int Length)
        {
            byte Crc = 0x7F;
            for (int i = 0; i < Length; i++)
            {
                Crc = (byte)(Crc - Buffer[Offset + i]);
                Crc = (byte)(Crc & 0x7F);
            }
            return Crc;
        }

        private static void Ext7(ref byte[] Buffer, int Offset, int Length)
        {
            byte Septett = 0;
            for (int i = 0; i < Length; i++)
            {
                if ((Buffer[Offset + i] & 0x80) == 1)
                {
                    Buffer[Offset + i] &= 0x7F;
                    Septett |= (byte)(1 << i);
                }
            }
            Buffer[Offset + Length] = Septett;
        }

        private static byte[] Inj7(byte[] Buffer, int Offset, int Length)
        {
            byte Septett = Buffer[Offset + Length];
            for (int i = 0; i < Length; i++)
            {
                if ((Septett & (1 << i)) == 1)
                {
                    Buffer[Offset + i] |= 0x80;
                }
            }
            return Buffer;
        }

        private static string b2h(byte[] comByte)
        {
            String builder = "";
            foreach (byte data in comByte) builder += Byte2Hex(data);
            return builder;
        }

        private static string Byte2Hex(byte b)
        {
            const string hex = "0123456789ABCDEF";
            int ln = b & 0x0F;
            int hn = (b & 0xF0) >> 4;
            string s = new string(new char[] { hex[hn], hex[ln] });
            return s;
        }

        static public void getData()
        {
            HIS.log.write("I", "VBUS : getData");
            SerialPort UART = new SerialPort("COM2", 9600);
            UART.ReadTimeout = 0;
            UART.Open();
            //for testing: UART.Flush();
            //for testing: UART.Write(VALUE, 0, VALUE.Length);
            //for testing: Thread.Sleep(100);

            byte[] rx_byte = new byte[1];
            byte Befehl = 0;
            byte Frames = 0;
            string Quelladresse = null;
            string Zieladresse = null;
            string Protokollversion = null;
            int temp1 = 0;
            int temp2 = 0;
            int temp3 = 0;
            int temp4 = 0;

            while (Befehl != 0x01) // wait for reported data
            {
                while (rx_byte[0] != 0xAA) // wait for transmission begin
                {
                    UART.Read(rx_byte, 0, 1);
                }

                byte[] header = new byte[9];
                for (int i = 0; i < 9; i++)
                {
                    UART.Read(rx_byte, 0, 1);
                    header[i] = rx_byte[0];
                }

                Quelladresse = b2h(new byte[] { header[3], header[2] });
                Zieladresse = b2h(new byte[] { header[1], header[0] });
                Protokollversion = b2h(new byte[] { header[4] });
                Befehl = header[6];
                Frames = header[7];

                if (CRC(ref header, 0, 8) == header[8])
                {
                    byte[] data = new byte[Frames * 6];
                    for (int i = 0; i < Frames * 6; i++)
                    {
                        UART.Read(rx_byte, 0, 1);
                        data[i] = rx_byte[0];
                    }

                    for (int i = 0; i < Frames; i++)
                    {
                        if (CRC(ref data, i * 6, 5) == data[i * 6 + 5])
                        {
                            data = Inj7(data, i * 6, 4);

                            switch (i)
                            {
                                case 0: // Frame1: "Temperatur Sensor 1", "Temperatur Sensor 1", "Temperatur Sensor 2", "Temperatur Sensor 2"
                                    temp1 = data[i * 6 + 0] + 256 * data[i * 6 + 1];
                                    temp2 = data[i * 6 + 2] + 256 * data[i * 6 + 3];
                                    break;
                                case 1: // Frame2: "Temperatur Sensor 3", "Temperatur Sensor 3", "Temperatur Sensor 4", "Temperatur Sensor 4"
                                    temp3 = data[i * 6 + 0] + 256 * data[i * 6 + 1];
                                    temp4 = data[i * 6 + 2] + 256 * data[i * 6 + 3];
                                    //$val[] = $VALUE[$i * 6 + 0 + 9] + 256 * $VALUE[$i * 6 + 1 + 9];
                                    //$val[] = $VALUE[$i * 6 + 2 + 9] + 256 * $VALUE[$i * 6 + 3 + 9];
                                    break;
                                case 2: // Frame3: "Betriebsstunden", "Betriebsstunden", "Drehzahl Relais 1", "Regelstatus"
                                    //$val[] = $VALUE[$i * 6 + 0 + 9] + 256 * $VALUE[$i * 6 + 1 + 9];
                                    //$val[] = $VALUE[$i * 6 + 2 + 9]; 
                                    //$val[] = $VALUE[$i * 6 + 3 + 9];
                                    break;
                                case 3: // Frame4: "Fehlermaske", "Leer", "Leer", "Leer"
                                    //$val[] = $VALUE[$i * 6 + 0 + 9];
                                    break;
                            }
                        }
                    }
                }
                if (temp1 > 1000) temp1 = temp1 - 32768;
                HIS.log.write("I", "VBUS : " + Quelladresse + " reported temp1 " + ((long)temp1).ToString() + "°C, temp2 " + ((long)temp2).ToString() + "°C, temp3 " + ((long)temp3).ToString() + "°C");
                HIS.ts1 += temp1;
                HIS.ts2 += temp2;
                HIS.ts3 += temp3;
                HIS.tsc++;

                Befehl = 0;
                Thread.Sleep(1000 * 10);
                //UART.Close();
                //UART = null;
                //return;
            }
            UART.Close();
            //Thread.Sleep(Timeout.Infinite);
        }
    }

The ‘switch’-construct has to be modified according to the type of solar controller you use. When installing the RSC-software from Redirecting... you find some XMLs with definitions of various controllers to match the frames sent per controller type.