problem decoding serial port data w/ VDT2

Hi everybody,
I'm having troubles trying to read out data from a temperature measuring and logging device called "Voltcraft 306" via the serial port RS-232. I managed to establish the connection on COM1 and communicate, i.e. send a command "K" asking for the device number and receiving "306". The problem I have now, is getting the data of interest, namely the actual temperature: I'm sending a command "A" and expect an answer consisting of 10 encoded bytes. Now, how can I decode them?!
For example i get "Àª≤v¿ˇ≤v"

My igor code is like this (string or binary readout deliver the same result):
Function rs_init()      // Initialize serial port
    VDT2/P=COM1 baud=9600,stopbits=1,databits=8,parity=0,in=0,echo=0,buffer=4096
    VDTOpenPort2 COM1           //Opens the named port, preparing it for use
    VDTOperationsPort2 COM1 //Designates a port as the port to use for command line operations
    VDT2 KillIO                 //Clear serial port
    Print "COM1 initialized"
End

Function rs_send(cmd)   // sends a command to the device
    String cmd 
    VDT2 KillIO     // clear port prior to use
    VDTWrite2 /O=3 cmd + "\r\n"     // send the command
End

Function/S rs_readstr() // reads out the string response frome the device
    String response
    //VDTRead2 /O=1/T="\r\n" response
    VDTRead2 /N=10 /O=3 /T="\r\n" response          // max 10 characters readout; timeout set to 3s
    print "answer from device: " + response
    return response
End

Function/S rs_readbin() // reads out the binary response frome the device
    String response
    VDTReadBinary2 /TYPE=(0x10) /S=10 /O=3 response
    print response
    return response
End

Function/S rs_query(cmd) // send cmd and return the response
    String cmd
    rs_send(cmd)
    return rs_readstr()
End

Thank you very much for your help!




Below you can see what the "A" command is supposed to deliver, taken out of the datasheet:
Command A: 1st BYTE: The first byte is the start byte, its value is 2. 2nd BYTE: bit7 Temperature Unit: 1->°C 0->°F bit6 Battery Condition: 1->Low Battery 0->Battery normal bit5 Hold: 1->Hold 0->not Hold bit4 -- no use -- bit3 TIME/Temperature Data in Bytes 6-9: 1->Indicates the LCD is displaying time bit2/bit1 MAX/MIN Mode 0 0 normal mode 0 1 MAXIMUN mode 1 0 MINIMUN mode 1 1 calculate MAX/MIN in background mode . bit0 REC (1->recording mode, 0->not recording) 3rd BYTE: bit0: T1 1->T1 is OL, 0->not OL (1) bit1: T1 sign 1->T1 value is minus, 0-> value is plus. bit2: T1 1->4th byte and 5th byte represent #### , 0->4th byte and 5th byte represent ###.# bit3: T2 1->T2 is OL, 0->not OL (1) bit4: T2 sign 1-> value is minus, 0-> value is plus. bit5: T2 1->8th byte and 9th byte represent #### , 0->8th byte and 9th byte represent ###.# bit6: 1->Memory is full. 0->Memory is not full. bit7: 1->Auto power off enabled. 0->Auto power off disabled. 4th BYTE: first two BCD code of T1 value. 5th BYTE: last two BCD code of T1 value 6th BYTE: If bit3 of 2nd BYTE =0 : first two BCD code of T1-T2 value. If bit3 of 2nd BYTE =1 : two BCD code of month. 7th BYTE: If bit3 of 2nd BYTE =0 : last two BCD code of T1-T2 value. If bit3 of 2nd BYTE =1 : two BCD code of day. 8th BYTE: If bit3 of 2nd BYTE =0 : first two BCD code of T2 value. If bit3 of 2nd BYTE =1 : two BCD code of hour. 9th BYTE: If bit3 of 2nd BYTE =0 : last two BCD code of T2 value. If bit3 of 2nd BYTE =1 : two BCD code of minute. 10th BYTE: end byte, its value is 3, 1st and 10th are used to check frame error.
Assuming that the data returned is binary, here is an example that might get you started:

Function Demo(response)
    String response             // 10 byte response from instrument
   
    Variable bit6Mask = 2^6     // Used for bit testing
   
    Variable first = char2num(response[0]) & 0xFF
    if (first != 2)
        Print "Error: First byte expected to be 2"
        return -1
    endif

    Variable second = char2num(response[1]) & 0xFF
    if (second & bit6Mask)
        Print "Low battery"
    else
        Print "Normal battery"
    endif
   
    return 0        // Success
End

Thank you very much for your hint. It helped me a lot since I can now read out all the single bits indicating the status of the device, the data format etc.
My remaining problem is now the temperature values themselves: They are - according to the manual - BCD coded (=binary coded decimal) and I just can't figure out how to decode them into decimals. The should be as follows:

4th BYTE: first two BCD code of T1 value 5th BYTE: last two BCD code of T1 value

So I'm expecting a value like ###.# °C as the other bytes tell me. I did an example measurement where I found that
4th BYTE: "11011101"
5th BYTE: "10101110"
should be -07.20 °C

I thought I have to split it up like this: "1101 1101 1010 1110" and then convert each 4bits into one digit. Am I wrong with this? Because the "1101" 4-bits are eleven in my calculation (1+2+0+8) , what can't be right in a decimal system ;)

I really hope you can help me again, greetings from munich!
jipi wrote:
I thought I have to split it up like this: "1101 1101 1010 1110" and then convert each 4bits into one digit. Am I wrong with this? Because the "1101" 4-bits are eleven in my calculation (1+2+0+8) , what can't be right in a decimal system ;)


This is correct so that means that your byte values are incorrect. I don't have an answer for that.

I would start by printing each of the byte values you read in hex:
Printf "%02X\r", aByteValue


Compare what you get to the documentation for the meaning of the byte values. If all of your other byte values make sense then you can presume that you are reading the data correctly and you then might ask the instrument manufacturer why these don't.

If the other byte values don't make sense then there is something wrong with the way you are reading the bytes or with the way you are extracting them from the Igor string, if that is how you are doing it.

Once you get the correct bytes, here is how you can convert from BCD to binary:

Function Demo()
    Variable fourthByte = 0x07
    Variable fifthByte = 0x20
   
    Variable value, digit

    digit = (fourthByte & 0xF0) / 16        // Zero
    value = digit

    digit = (fourthByte & 0x0F)         // Seven
    value = 10* value + digit

    digit = (fifthByte & 0xF0) / 16     // Two
    value = 10* value + digit

    digit = (fifthByte & 0x0F)          // Zero
    value = 10* value + digit
   
    Print value
End