Shop OBEX P1 Docs P2 Docs Learn Events
DS2760 Thermocouple Code needs review - 2's complement problem? — Parallax Forums

DS2760 Thermocouple Code needs review - 2's complement problem?

Timothy D. SwieterTimothy D. Swieter Posts: 1,613
edited 2008-11-15 03:14 in Propeller 1
I attached my first pass at creating Propeller code for the DS2760 thermocouple kit. I wanted to get the opinions and feedback from the forum before I posted the code into the object exchange.

In general, the code works, but there are a couple times when it does "funky things". I believe that the problem is with the two complement and the math going on. I tried following some of the Basic Stamp demo code, I also reviewed another post on the Propeller forum. In the end though there are times when I get unexpected results. Those results are mostly when the Cold Temperature Junction (CJ) and the Thermocouple Junction (TJ) are the same temperature or more likely when the TJ is lower than the CJ. I have starred at the code and tried several things but I think I am missing something fundamental that is needed in order to make the code more robust.

So, have at it and let me know what you think should be improved. I have a test setup of the thermocouple here that I can try out any modifications if you need me to.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
www.tdswieter.com

Post Edited (Timothy D. Swieter) : 11/14/2008 12:24:28 PM GMT

Comments

  • StefanL38StefanL38 Posts: 2,292
    edited 2008-11-11 19:35
    Hello Timothy,

    as I don't have a thermocouple-modul laying around here
    it is hard to debug the problem

    could you provide a table of values some working correct some incorrect
    three columms:
    1 measured temperature
    2 RAW data coming in from the measuringdevice and
    3 transformed data

    best regards

    Stefan
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-12 11:48
    Stefan,

    Why of course I can provide data - excellent question. I had to take a step or two back in my code writing to get back to a debugging state where I could output the raw thermocouple data.

    I attached a text file. I posted a snippet of the data below. The text file has a column of Thermocouple Voltage (as measured by the DS2760), the Cold Junction temperature (the temp of the IC measured by the IC), the calculated Thermocouple Temp and "time" which is just a half second tick mark for some time vs temp testing I was doing.

    TC Volt    CJ Temp    TC temp    time
    0    25    25    0
    0    25    25    1
    0    25    25    2
    0    25    25    3
    0    25    25    4
    0    25    25    5
    0    26    26    6
    119793    25    223    7
    0    25    25    8
    0    25    25    9
    0    25    25    10
    119793    25    223    11
    119793    25    223    12
    119793    25    223    13
    
    



    It appears the data does not post well in the code block. Open the attached text to read it better. The superious "223" in the TC Temp column are not right. I have also seen it where the TC Temp returns 7 when it is clearly not 7c at the thermocouple. This is happening, I think, when the TC Voltage/temperature is below the CJ temperature. I am fairly certain this is a sign problem. I also think that the code could be optimized too. I would like to learn of any suggestions.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • TJHJTJHJ Posts: 243
    edited 2008-11-13 01:41
    Here is the type K table formatted in the same method as you used and a modification of the search method to account for the larger table size.

    Maybe if you want to include it in the final driver file.

    TJ

    I cant seem to upload it right now, Ill try again later.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-13 01:47
    Have the upload be the zip file. I will take a look at it and sure I can include the K-table in final driver. I will review your search algorithm too and see what is the best solution for having multiple tables. Maybe the end user simply comments and uncomment a routine or table for their needs so the code isn't larger than is needed.

    I don't want to "release" or post the object in the exchange until the kinks of the calculations are worked out. I want the object to work succesfully and reliable for temps from 0c and above. Maybe a future revision can include the below 0c temps, but for now my needs don't need that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com

    Post Edited (Timothy D. Swieter) : 11/13/2008 1:54:29 AM GMT
  • TJHJTJHJ Posts: 243
    edited 2008-11-13 04:50
    So upload try now, I also included a slightly different search routine, that in worst case for the 1240 point Type K table, should only loop 28 times, that is if the temperature was 1199. So just a thought for a little different search system.

    Also my ds2762 chips with nothing hooked up to them show 7 deg c. Not sure if that helps the issue.

    Hope this helps.
    TJ

    EDIT : Do you live in a cold area, the chip surface temperature is 16 deg C, from my Ir temp gun, So Im thinking in the tcvolt ~> 3, is somehow leaving the bit held in 8 in there, causing it to be subtracting 8 from the total temp, instead of moving it out to bit 31 or bit 15.

    Im not sure if Im making any sense here.

    Post Edited (TJHJ) : 11/13/2008 5:19:41 AM GMT
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-13 06:59
    I saw the 7 deg C thing too but I couldn't capture that data when I was making my post above.

    Nope, I am not in a cold area. When I saw 7c my IC was about 25c and I confirmed that with my IR temp gun as well. I am glad I bought it now.

    I will have a look at your upload tonight or tomorrow when I get back to the code.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-13 14:21
    I downloaded your code TJHJ and placed the K-type table into the object I am working on. Thank you for posting that, I think others will get use out of it.

    I also reviewed your search algorithm. I like it. I can see how it is faster. I thought it could be improved so I sat down and did some changes, but I can't get my code to work at all. I don't think it is is the search algorithm though. Tonight has been a weird night of coding because it seems like multiple aspects of my design is not working and equipment failing and then working. My thermocouple was acting up, my AC controls were acting up. Everything seemed to work and then not work. Even though I am trying to code, test code, test one part of the system at a time, and right now it is the thermocouple, it seems like proven parts were misbehaving. So, I set it aside for now and will get back to it tomorrow or Saturday.

    Oh, the thing I tried to improve. I like how the search algorithm was simple. The thing I am a bit paranoid on was the code getting stuck in the repeat loop forever because some unexpected value getting entered as the parameter. So I was changing the repeat statements to be "repeat t from x to y step DDD" coding. This was adding some other checks in the code. I think it will work, but it is slower.......Hey wait a minute. Inspiration!!! At the top of the TJHJ's algorithm a check on the extremes could be done and the code exited there if the parameter doesn't pass that test, then the "repeat until x" style of code would have good reason to complete.

    I hope these ramblings make sense.

    Another thought, in Spin there is a lookdown and lookup. I think I should research if those operators work with data in the "dat" section of the code. Then maybe the search algorithm can be easier yet.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • TJHJTJHJ Posts: 243
    edited 2008-11-14 01:14
    Oh it can be improved, I just came up with it and it is the first time I have tried it.
    Two thought I think your doing one but just making sure.

    1. Do a 1/2 range check at the start and will stop it going off the table and will cut the 1st search step in 1/2.
      SearchStartVar := -1
      if TempMvValue >= table[noparse][[/noparse]min] and TableMvValue < table[noparse][[/noparse]max/2]
        SeachStartVar := min
      elseif TempMvValue >= table[noparse][[/noparse]max/2] and TempMvValue <= table[noparse][[/noparse]max]
        searchStartVar := max/2
    
    
    if seachStartVar <> -1
      ' search here. 
      'This is where thought two comes in
      
      'It steps up from searchStart var to limit max 
        'checking by steps of 100 going up
      
      ' Instead of backing up 100 by subtracting 100
      
      ' Have the next seach go down by 10. 
    
             'until tempMvValue < table[noparse][[/noparse]x]
    
      ' Now step back up again
    
    



    it saves a whole step at the end of each loop, Ive got a thought for a floating step option but still working on it.

    TJ
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-14 01:16
    Excellent. If you can post more by tonight I will look in to it, assuming I get my other kinks worked out.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • TJHJTJHJ Posts: 243
    edited 2008-11-14 01:37
    Ok so here it is, raw and only tested once. I am totally undecided if will be any faster in the end because it executes so much more every loop.

    Thought just hit me, Why not just save the last temp, and start the search there? The temp change is very slow of a thermocouple by comparison to the looping speed, so normally we shouldn't make to many steps away if we start the search at the old value with an if then statement.


    Pub Search(MvValue) | searchstep, Direction, seachPoint
    Direction := 1
    searchStep := (Maximum+Minimum)/2
    searchPoint := Minimum 'EDIT PLACED HERE, Make sure we start at the bottom so the code is more universal
    'Make sure we are in the range 1st. 
    if (MvValue > table[noparse][[/noparse]Minimum] and MvValue < table[noparse][[/noparse]Maximum])
      'now repeat while we are in the bounds of the table and havent found it.
      repeat while (searchPoint >= Minimum and searchPoint <= Maximum ) and searchStep > 0
    
        if MvValue > table[noparse][[/noparse]searchPoint]      'if value > table, and we moving up 
            if direction == -1               ' We just switched Directions
              SeachStep := SearchStep/2      ' Half our step size
              direction := 1                 ' Same direction of movement dont 1/2 step size
              
           SearchPoint := SearchStep + SeachPoint    '  Add the same step until we pass over the value then well 1/2 it again
        elseif MvValue <  table[noparse][[/noparse]searchPoint]         ' We have gone to far so now we need to step down. 
            if direction == 1                        ' We were stepping up, but we over shot it. 
              SeachStep := SearchStep/2              ' So 1/2 our step and go down
              Direction := -1                        ' We were moving down so keep doing that at the same 
                      
            SearchPoint := SearchPoint - SearchStep  ' move down till we pass over it again.
    
         ' We should exit the loop when SearchStep = 0, but just to make sure.
        if seachStep == 0
          quit    
    
    
    
    



    where minimum is the smallest allowable table value, and maximum is the largest allowable table value,

    Post Edited (TJHJ) : 11/14/2008 1:46:04 AM GMT
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-14 12:21
    OK - I think I am getting off track following the optimizing of the search algorithm. I can come back to that later. TJ, I like what you are showing so I certainly want to try it once the other calculation problems are fixed.

    My immediate problem I think is a 2's complement problem. The problem is occurring when the thermocouple temperature is higher than the cold junction temperature (IC temperature). The problem is occurring in the routine reading the thermocouple voltage though and not in the other processing routines. Here are the results of some testing.

    
    '***************************************
    PUB readTCvolt              
    '***************************************
    ''The voltage across the external thermocouple wires
    ''two complement format, resolution of 15.625µV
    '' &#9484;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9488; &#9484;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9488;
    '' &#9474; S &#9474;2^11&#9474;2^10&#9474;2^9&#9474;2^8&#9474;2^8&#9474;2^6&#9474;2^5&#9474; &#9474;2^4&#9474;2^3&#9474;2^2&#9474;2^1&#9474;2^0&#9474; x &#9474; x &#9474; x &#9474;
    '' &#9492;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9496; &#9492;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9496;
    ''  MSB         Add OE          LSB    MSB         Add 0F          LSB
    ''
    ''  This routine returns microvolts (µV)
    
      'Read the two registers of data out of the DS2760    
      OW.reset
      OW.writeByte(_SKIP_NET)
      OW.writeByte(_READ_DATA)
      OW.writeByte(_Current_MSB)
      tc_voltage.byte := OW.readbyte
      tc_voltage.byte[noparse][[/noparse]0] := OW.readbyte
    
      return(tc_voltage)    
    
    



    The above code returns the raw register results. The values I get are as follows. These numbers are two's complement, so the large number is more like a small negative number.
    TC Volt    (raw data)
    8
    16
    16
    8
    16
    16
    16  <- put finger on IC to make it warmer than TC
    8
    0
    65520
    65504
    65464
    65464
    65468
    65440 remove finger and system returns, in time to as before 
    
    



    Then when I add in the processing such as the following at the end of the one-wire reading.
     .
     .
     .
      tc_voltage ~>= 3                                     'Remove don't cares and make sure sign stays right
      tc_voltage := (tc_voltage * 15) + (tc_voltage ** 2_684_354_560) 'multiply by 15.625. 0.625 ~=2684354560/4294967296
      return(tc_voltage)
    
    



    I get the following results.
    TC Volt (with processing)
    14
    29
    29
    29
    14
    29
    14
    0        <-put finger on the IC
    54257
    54052
    54008
    
    



    The raw results posted first make sense to me. The voltage of the thermocouple being read changes sign. So I understand going from 0 to a really large number which in reality is a small negative number. With the processing results however, the results are going from 0 to a large negative number and I expect it to be a small negative number.

    Another post on the forum has referenced this: http://forums.parallax.com/showthread.php?p=682102 The conversation said that the processing being used above may not be accounting for the sign in the two's complement and recommended another method. So I substituted the processing above for the following.

      tc_voltage ~>= 3                                     'Remove don't cares and make sure sign stays right
      tc_voltage := tc_voltage * 125 ~> 3
      return(tc_voltage)
    
    



    and the results are similar to the other processing results.
    75
    30
    30         <-- put finger on the IC
    57329
    57314
    57299
    
    



    So - the problem I want to solve at the moment is how to take the raw value from the DS2760 and get it into a state for processing by the other routines. What I am trying to do is move the value right to get rid of the don't cares in the register. Then multiple it by 15.625 (15 5/8) to get the value of TC_voltage to be in uVolts.

    On a side not I am curious why my finger being present by the IC causes the thermocouple voltage to change. Maybe it is the fact that my finger is near the thermocouple ends and heating those when my finger is touching the IC.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-14 13:12
    Maybe this is another clue. The tc_voltage noted above is defined as a WORD. I am now playing around with tc_voltage ~>= 3 and it looks like it is not sign extending as I thought it should because it is producing the same results as tc_voltage >>= 3.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com
  • TJHJTJHJ Posts: 243
    edited 2008-11-14 18:09
    I think I see it, Your using a long based sign extend, ~> is for a long, on a word. So its just leaving the sign in position 15.

    So here are my suggestions.


    Maybe try the hard way sign extend, and if its not negative just push it off the end.



    like so.
    if tc_voltage.byte & %1000_0000 'Cant remember and I dont have the manual with me, bitwise and is one & or 2?
      tc_voltage << 16 >> 16+3 ' One more to push it off the end of the variable. Then move it back to the end, this ditches the whole sign bit. 
      ' now deal with the .125 issues. 
    
    or 
    var
    
    long currentVoltage, coldJunction
    
    coldJunction := (~~cjComp) ~> 3 ' Or 6 depending on how your doing the .125 multiply.  
    currentVoltage := ~~tc_voltage
    if currentVoltage > 0 ' Sign extend it before you move it. 
       currentVoltage := (currentVoltage ~> 3 ) + coldJunction ' So now the sign is out in 31, move it back 3
    else
       currentVoltage := 0
    
    
    or.....
    
    'Because I think for the intermediate assignments are always treated as a long, not a word. 
    CurrentTemp := ( (~~tc_voltage) ~> 3) + (~~cj_comp ~>3 ) ) ' this way its sign extended and added in the intermediate assignment, all treated as a long, then we store it back in the word size result. 
    
    



    Or just stuff it in a long, its not as efficient, but it should work correctly.

    Any luck?


    EDITED : To add 3rd idea.

    Post Edited (TJHJ) : 11/14/2008 6:26:12 PM GMT
  • Greg NortonGreg Norton Posts: 70
    edited 2008-11-15 02:50
    Timothy,

    I think TJHJ has hit on it, I ended up using a temporary variable to make sure we're dealing with 32 bits. Here is some code I had success with. There's probably a more efficient way to eliminate temp1, but this seems to be working.

    Greg

    PUB get_tc_voltage | temp1
      ow.reset
      ow.writeByte(SKIP_ROM)
      ow.writeByte(READ_DATA)
      ow.writeByte(I_REG_MSB)
      raw_voltage.byte := ow.readByte                    ' Get the raw value from the current register
      raw_voltage.byte[noparse][[/noparse]0] := ow.readByte
      temp1 := ~~raw_voltage                                ' Sign extend to 32 bits    
      temp1 := temp1 ~> 3                                   ' Correct alignment
      result      := (temp1 * 125) ~> 3                     ' Multiply by 15 5/8, Return voltage in microvolts
    
    



    PS - the forum seems to be mucking up the code a little bit. That first read goes in to byte 1 of raw_voltage, somehow the left bracket, 1, and right bracket disappeared.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-15 03:14
    Thanks for the confirmation guys. Last night before I called it a night I figured out some of the long/2's complement stuff. I was reading about longs, >> and such in the Propeller manual. Your postings confirm what I was thinking. I have been testing an object this morning and I think it is better than the previous one posted in this thread. Therefore I uploaded it to the exchange. I don't think it is perfect yet, but it seems to be stable for what I am doing. I also implemented the idea of storing the previous temperature in the table search routine to speed finding the correct value.

    If you have time, take a look at the object and let me know what you think and if you see other areas to improve.

    Here is the object: obex.parallax.com/objects/385/

    I need to move on to coding other portions of my project now. Since the code is "stable" based on my limited testing, I will leave it for now and come back to it in a couple days.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto fo SunSPOT, BitScope
    www.tdswieter.com

    Post Edited (Timothy D. Swieter) : 11/15/2008 3:20:03 AM GMT
Sign In or Register to comment.