Shop OBEX P1 Docs P2 Docs Learn Events
Reading a MAX 31855 — Parallax Forums

Reading a MAX 31855

Going to need a bit of help on this one. I am working with the M31855K and am trying to write a SPIN function to read the temperature of the type K sensor. I have found the Github example, but it appears to only work with Prop 2? New to that area... The Github example seems to be missing several things and I can't seem to get it to run. So... I am wanting to just write my own function in the Prop Tool.

After looking at the Data Sheet, I am a bit confused. It looks like I need to pull CS low, then begin pulsing SCK to receiving in data on SO. There are 32 bits that would need to be read, filled into an array, and then the first 14 bits would be the temperature? Not sure I understand how to convert those 14 bits to a human readable temperature. Any help is greatly appreciated!

Comments

  • I wrote this for a client app (industrial HVAC) a long time ago -- it worked fine back then.
  • I've used your 31855 demo before and it worked really good. The max31855 itself works good with short cable, but will signal fault codes with long unshielded thermocouple extension cable.
  • Here are a couple I wrote for a Sparkfun board:

  • Thank you for the code! I have modified my code to work with JonnyMac's functions and have run into a couple of issues.

    The first being the Cold Junction and the TC junction are way apart (+/- 10ºF). Is there a way to programmatically tune to the correct temperature? It seems the code returns a temperature reading in Celsius where I would need Fahrenheit for this application.

    Second, since the code conversion from C to F is starting from a whole number, it skips degrees when converting to F which can be an issue since this will be used in a tempering oven and the temperature needs to hold very steady for well over an hour. A swing of +/- 10 degrees F can result in a failure.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      temp_CS = 0
      temp_SCK = 1
      temp_SO = 2
    
      ' Serial Terminal Stuff
      DEBUG_BAUD = 9_600
      DEBUG_HEADING_X = 1          ' Output formatting data
      DEBUG_HEADING_Y = 1
      DEBUG_DYNAMIC_X = DEBUG_HEADING_X + 10
      DEBUG_DYNAMIC_Y = DEBUG_HEADING_Y + 2
    
    VAR
      BYTE buffer[256]
      BYTE value1
      
      
    OBJ
      Pst           : "Parallax Serial Terminal"
      temp          : "jm_max31855"
      math          : "FloatMath"
      fstr          : "FloatString"
    
    PUB go | deg, cj_temp, tc_temp
      pause(1000)
      temp.start(temp_CS, temp_SCK, temp_SO, -1)
      Pst.Start(DEBUG_BAUD)                                                         '1 Cog
      
      Pst.Clear
      Pst.Position(DEBUG_HEADING_X, DEBUG_HEADING_Y)
      Pst.Str(string("Current Position", 13))
      Pst.PositionX(DEBUG_HEADING_X)
      Pst.Str(string("------------------------", 13))
      Pst.PositionX(DEBUG_HEADING_X)
      Pst.Str(string("Value  ................", 13))
    
      repeat
        cj_temp := math.FFloat(temp.read_cj(1))
        tc_temp := math.FFloat(temp.read_tc(1))
        
        Pst.Position(DEBUG_DYNAMIC_X, DEBUG_DYNAMIC_Y)
        'Pst.Str (fstr.FloatToString(cj_temp))
        Pst.Str (fstr.FloatToString(CtoF(cj_temp)))
        Pst.Str(string("..."))
        Pst.Position(DEBUG_DYNAMIC_X, DEBUG_DYNAMIC_Y + 1)
        Pst.Str (fstr.FloatToString(CtoF(tc_temp)))
        Pst.Str(string("..."))
        pause(100)
        
    PUB CtoF (deg_c): deg_f
    ' 9/5 = 1800 + 32
        deg_f := math.FAdd (math.FMul (deg_c, 1.80), 32.00)
        return deg_f
    
    PUB Update_Debug_Window
    
        return
    
    PUB pause(Duration)
      if(Duration > 0)  
        waitcnt((clkfreq / 1_000 * Duration) + cnt)
      return
    
  • ChrisGadd wrote: »
    Here are a couple I wrote for a Sparkfun board:

    I tried to get these to work, but it kept returning 0ºC which made me think either I have the pins set wrong or the PU resistor is not right?
  • JonnyMacJonnyMac Posts: 9,159
    edited 2020-07-29 21:18
    I've never been a fan of the floating point math libraries. In 15 years of Propeller coding I used one on a single project (geo location device). If you stick with fixed-point math you can keep things in 0.25 degree C increments. Here's a bit of code that will help.
      tc100 := (ts.read_raw ~> 18) * 25                             ' convert raw to 1/100ths C
      tf100 := tc100 * 9 / 5 + 32_00                                ' convert to 1/100ths F
    
    Is converting to Fahrenheit necessary? Conversions introduce rounding errors.

    Remember that your values are 100x the actual temperature: 23.5 degrees C will be 2350 using fixed-point math.
  • I use these all of the time with my own version of the JonnyMac spin object (Thanks JonnyMac) Works no problem.
    1536 x 2048 - 770K
  • I run all of the Sck. pins together to one prop pin and So. pins altogether, then just chip select the one I want to read.
  • I use the floating math and convert to C to F
  • max72max72 Posts: 1,155
    DigitalBob wrote: »
    I've used your 31855 demo before and it worked really good. The max31855 itself works good with short cable, but will signal fault codes with long unshielded thermocouple extension cable.

    Are you twisting the cables?

    Massimo
  • ChrisGadd wrote: »
    Here are a couple I wrote for a Sparkfun board:

    I tried to get these to work, but it kept returning 0ºC which made me think either I have the pins set wrong or the PU resistor is not right?

    I'd say check the pin assignment. I just tested it again and it works fine with a pull-up on SCK of up to 1.3M, only fails at 1.5M. The SparkFun board doesn't look like it should be causing any oddities, just has a 10K pullup on CS and filtering on the thermocouple inputs.

    I agree entirely with Jon; I've dabbled a little with floating points and decided it didn't offer enough benefit over integer math.
    Try this for a comparison:
      fds.start(31,30,0,115200)
      i := 0
      repeat
        repeat until fds.rx                              ' Press any key to begin
        repeat 256
          fds.dec(i * 9 / 5 + 3200)
          fds.tx($09)
          fds.str(fstr.FloatToString(math.Fadd(math.Fmul(math.Fdiv(math.Ffloat(i),100.00),1.80),32.00)))
          fds.tx($0D)
          i++
    
    Do you need those thousandths of degrees?
  • Thermocouple wire has a resistance loop, ohms per ft. If you run long cables of a small gauge, then the resistance is high.
    When I'm using the sparkfun board I don't use CS pullup's.
  • JonnyMac wrote: »
    I've never been a fan of the floating point math libraries. In 15 years of Propeller coding I used one on a single project (geo location device). If you stick with fixed-point math you can keep things in 0.25 degree C increments. Here's a bit of code that will help.
      tc100 := (ts.read_raw ~> 18) * 25                             ' convert raw to 1/100ths C
      tf100 := tc100 * 9 / 5 + 32_00                                ' convert to 1/100ths F
    
    Is converting to Fahrenheit necessary? Conversions introduce rounding errors.

    Remember that your values are 100x the actual temperature: 23.5 degrees C will be 2350 using fixed-point math.

    That worked perfectly :) Since I plan on making several of these for some of our local blacksmiths and one for myself, using Fahrenheit is the easiest to read for us.

    So... the other issue I am running into is the calibration. For testing purposes, I am using a thermocouple that came with my Southwire meter which is a K type. I am using ambient room temperature for a general temperature. The room temperature is at 74, but the average readings are ranging from 59 to 63 on the TC reading. If I apply any heat at the IC itself, the reading skyrockets which I don't think that is supposed to happen since I am reading the TC instead of CJ, but I could be wrong.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      temp_CS = 0
      temp_SCK = 1
      temp_SO = 2
    
      ' Serial Terminal Stuff
      DEBUG_BAUD = 9_600
      DEBUG_HEADING_X = 1          ' Output formatting data
      DEBUG_HEADING_Y = 1
      DEBUG_DYNAMIC_X = DEBUG_HEADING_X + 10
      DEBUG_DYNAMIC_Y = DEBUG_HEADING_Y + 2
    
    VAR
      LONG temp_array[100]
    
    OBJ
      Pst           : "Parallax Serial Terminal"
      temp          : "jm_max31855"
    
    PUB go | pointer, deg, cj_temp, tc_temp, tf_temp
      bytefill(@temp_array, 0, 100)
      pointer := 0
      pause(1000)
      temp.start(temp_CS, temp_SCK, temp_SO, -1)
    
      Pst.Start(DEBUG_BAUD)                                                         '1 Cog
      
      Pst.Clear
      Pst.Position(DEBUG_HEADING_X, DEBUG_HEADING_Y)
      Pst.Str(string("Current Position", 13))
      Pst.PositionX(DEBUG_HEADING_X)
      Pst.Str(string("------------------------", 13))
      Pst.PositionX(DEBUG_HEADING_X)
      Pst.Str(string("Value  ................", 13))
    
      repeat
        tc_temp := (temp.read_raw ~> 18) * 25                             ' convert raw to 1/100ths C
        tf_temp := tc_temp * 9 / 5 + 32_00                                ' convert to 1/100ths F
        temp_array[pointer] := tf_temp
        pointer++
        if pointer == 101
          pointer := 0
        
        Pst.Position(DEBUG_DYNAMIC_X, DEBUG_DYNAMIC_Y)
        Pst.Dec(getAverage(@temp_array, 100))
        Pst.Str(string("..."))
        Pst.Position(DEBUG_DYNAMIC_X, DEBUG_DYNAMIC_Y + 1)
        Pst.Dec(temp_array[pointer - 1])
        Pst.Str(string("..."))
        pause(100)
    
    PUB getAverage(the_array, sample_count) | i, arraysum
        arraysum := 0
        repeat i from 0 to sample_count
          arraysum += long[the_array][i]
        return arraysum / sample_count
    
    PUB pause(Duration)
      if(Duration > 0)  
        waitcnt((clkfreq / 1_000 * Duration) + cnt)
      return
    
  • Are you using the Omega connector on the sparkfun board? My CJC and probe temps. Are within 1 degree when exposed to the same temp. I use my finger on the module to raise the temp. I"ved use some cheap Amazon K temp. Probes and they worked Ok, just watch for breaks in the probe wire.
  • I am using my own custom circuit board that has been modified to work with this IC. Once I establish a good test board, I will design a new one that better fits this application, but I need to work out the bugs first. If the board temperature makes a difference, does that become an issue being that it will be mounted next to an oven (~1500ºF) that may increase the temperature of the board by 10 degrees or more than ambient temperature?

    I will be ordering the K Type thermocouple wire from a quality source and TIG welding the wire together for the final builds.
  • Oh, I thought you had a Sparkfun board. You might want to buy one sparkfun board and test your system. On yours did you use the ferrite beads on the TC line into the IC?. You can read the main probe and CJC. As you know CJC is for temp. correction.
  • I am using my own custom circuit board that has been modified to work with this IC. Once I establish a good test board, I will design a new one that better fits this application, but I need to work out the bugs first. If the board temperature makes a difference, does that become an issue being that it will be mounted next to an oven (~1500ºF) that may increase the temperature of the board by 10 degrees or more than ambient temperature?

    I will be ordering the K Type thermocouple wire from a quality source and TIG welding the wire together for the final builds.

    That is a difficult situation for thermocouple instrumentation. Avoid all gradients of temperature across the circuit board from the MA31855 to the point where the thermocouples attach. Avoid thermal gradients across the chip itself. It is gradients that matter, not so much the increase in temperature per se, so do all you can to isolate the board from the source of heat, so that its temperature will be uniform. Attach the thermocouple itself or the connector K extensions as close as possible to the MAX; even to the point of soldering the thermocouple wires directly to MAX pins.



  • I know this is a bit old, but I had to put this project on the back burner for a little while I finished up another project. I have something different happening this time and I believe it is something with external "noise". I moved the circuit to my home computer and started running it off a battery instead of a digital PSU and I instantly saw major fluctuations in the temperature readings....like 50+ degrees. As soon as touch anywhere on the board, the temperature instantly shoots up closer to the room temperature, but was still not within 10 degrees according to the PST output. I then added a 2x16 display to display the output that way and remove the PST and Prop Tool from the equation and now the reading are within 1 deg and don't seem to fluctuate anymore. How would I be able to minimize "outside noise" from this circuit? Is a ferrite bead mandatory to eliminate this noise?
  • The ferrite beads would help
  • K2K2 Posts: 693

    @JonnyMac said:
    I've never been a fan of the floating point math libraries. In 15 years of Propeller coding I used one on a single project (geo location device). If you stick with fixed-point math you can keep things in 0.25 degree C increments. Here's a bit of code that will help. tc100 := (ts.read_raw ~> 18) * 25 ' convert raw to 1/100ths C tf100 := tc100 * 9 / 5 + 32_00 ' convert to 1/100ths F

    Is converting to Fahrenheit necessary? Conversions introduce rounding errors.

    Remember that your values are 100x the actual temperature: 23.5 degrees C will be 2350 using fixed-point math.

    Like Heater used to say: If you think you need floating point, chances are you don't understand the problem.

    I don't want to put words in eagletalontim's mouth but I've observed the same thing when converting from whole number C degrees to whole number F degrees. The process loses resolution because a Celsius degree is only 5/9ths of a Fahrenheit degree. So you see the Fahrenheit temperature skipping certain numbers even though the rise or fall of temperature is monotonic.

    To cure that, I round off by adding half a degree on the last conversion step (... + 32_50) and then truncating (/100).

    As for why I'm using Fahrenheit (seems like it needs justification these days), it's because I've been firing and baking for 60 years and have a sense for F that I will never have for C. Conversely, C is all I've ever used for chemistry and physics, so F in a scientific context is awkward and objectional. ¯_(ツ)_/¯

Sign In or Register to comment.