I am new to Python coding and am having a few issues trying to get a ESP8266 working with 2x Max31865 boards. I have done a bit with Java for HMI's as I am more involved with PLC programming but nothing like this. I can work my way through some of the code and how it works but I am getting errors when I try running it. Currently I only have one board connected. I have found some code online that should work and have copied it but no luck. Basically it is now throwing the following error that I can not get past. All of the pins are as per below and wired up. Is anyone able to help. Eventually I will be reading from two boards and doing some calculations as it will be a solar controller for my pool.
>> %Run -c $EDITOR_CONTENT
Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead
Traceback (most recent call last):
File "<stdin>", line 31, in <module>
File "adafruit_max31865.py", line 66, in __init__
TypeError: can't convert SoftSPI to int
Attached is my current code. The Adafruit_Max31865 library I copied from their website and as it is written in circuit python, I have changed some of the parameters from requiring SPI_device to SPI. However as per the fault above, I changed it to SoftSPI
Main.py
Code: Select all
## MicroPython Imports
import time
import machine
## Local Imports
import adafruit_max31865 as max31865
RTD_NOMINAL = 100.0 ## Resistance of RTD at 0C
RTD_REFERENCE = 430.0 ## Value of reference resistor on PCB
RTD_WIRES = 3 ## RTD 3 wires
## Create Software SPI controller. MAX31865 requires polarity of 0 and phase of 1.
## Currently, the micropython on the ESP32 does not support hardware SPI
sck = machine.Pin(14, machine.Pin.OUT)
mosi = machine.Pin(13, machine.Pin.IN)
miso = machine.Pin(12, machine.Pin.OUT)
spi = machine.SPI(baudrate=50000, sck=sck, mosi=mosi, miso=miso, polarity=0, phase=1)
## Create array SPI Chip Select pins
#cs1 = machine.Pin(33, machine.Pin.OUT, value=1)
#cs2 = machine.Pin(15, machine.Pin.OUT, value=1)
#cs3 = machine.Pin(32, machine.Pin.OUT, value=1)
#cs4 = machine.Pin(14, machine.Pin.OUT, value=1)
#css = [cs1, cs2, cs3, cs4]
cs1 = machine.Pin(15, machine.Pin.OUT, value=1)
css = [cs1]
sensors = []
idx = 0
## Create array of active RTD sensors and information about them
for cs in css:
idx += 1
sensors.append(
max31865.MAX31865(
spi, css[idx-1],
wires = RTD_WIRES,
rtd_nominal = RTD_NOMINAL,
ref_resistor = RTD_REFERENCE)
)
def timestamp():
return float(time.ticks_ms()) / 1000.0
boot_time = timestamp()
while True:
data = [timestamp() - boot_time] + [sensor.temperature for sensor in sensors]
print(','.join(map(str,data)))
Code: Select all
"""
`adafruit_max31865`
====================================================
MicroPython module for the MAX31865 platinum RTD temperature sensor. See
examples/simpletest.py for an example of the usage.
* Author(s): Tony DiCola, original CircuitPython version
Chris Osterwood, port _read and _write methods to MicroPython
"""
import math
import time
from micropython import const
import machine
#pylint: disable=bad-whitespace
# Register and other constant values:
_MAX31865_CONFIG_REG = const(0x00)
_MAX31865_CONFIG_BIAS = const(0x80)
_MAX31865_CONFIG_MODEAUTO = const(0x40)
_MAX31865_CONFIG_MODEOFF = const(0x00)
_MAX31865_CONFIG_1SHOT = const(0x20)
_MAX31865_CONFIG_3WIRE = const(0x10)
_MAX31865_CONFIG_24WIRE = const(0x00)
_MAX31865_CONFIG_FAULTSTAT = const(0x02)
_MAX31865_CONFIG_FILT50HZ = const(0x01)
_MAX31865_CONFIG_FILT60HZ = const(0x00)
_MAX31865_RTDMSB_REG = const(0x01)
_MAX31865_RTDLSB_REG = const(0x02)
_MAX31865_HFAULTMSB_REG = const(0x03)
_MAX31865_HFAULTLSB_REG = const(0x04)
_MAX31865_LFAULTMSB_REG = const(0x05)
_MAX31865_LFAULTLSB_REG = const(0x06)
_MAX31865_FAULTSTAT_REG = const(0x07)
_MAX31865_FAULT_HIGHTHRESH = const(0x80)
_MAX31865_FAULT_LOWTHRESH = const(0x40)
_MAX31865_FAULT_REFINLOW = const(0x20)
_MAX31865_FAULT_REFINHIGH = const(0x10)
_MAX31865_FAULT_RTDINLOW = const(0x08)
_MAX31865_FAULT_OVUV = const(0x04)
_RTD_A = 3.9083e-3
_RTD_B = -5.775e-7
#pylint: enable=bad-whitespace
class MAX31865:
"""Driver for the MAX31865 thermocouple amplifier."""
def __init__(self, spi, cs, *, rtd_nominal=100, ref_resistor=430.0, wires=2):
self.rtd_nominal = rtd_nominal
self.ref_resistor = ref_resistor
self._device = machine.SoftSPI(spi, cs)
# Set wire config register based on the number of wires specified.
if wires not in (2, 3, 4):
raise ValueError('Wires must be a value of 2, 3, or 4!')
config = self._read_u8(_MAX31865_CONFIG_REG)
if wires == 3:
config |= _MAX31865_CONFIG_3WIRE
else:
# 2 or 4 wire
config &= ~_MAX31865_CONFIG_3WIRE
self._write_u8(_MAX31865_CONFIG_REG, config)
# Default to no bias and no auto conversion.
self.set_bias(False)
self.set_auto_convert(False)
def _read_u8(self, address):
# Read an 8-bit unsigned value from the specified 8-bit address.
buf = []
with self._device as device:
device.write(bytes([address & 0x7F]))
buf = device.read(1)
return buf[0]
def _read_u16(self, address):
# Read a 16-bit BE unsigned value from the specified 8-bit address.
buf = []
with self._device as device:
device.write(bytes([address & 0x7F]))
buf = device.read(2)
return (buf[0] << 8) | buf[1]
def _write_u8(self, address, val):
# Write an 8-bit unsigned value to the specified 8-bit address.
with self._device as device:
buf = bytearray(2)
buf[0] = (address | 0x80) & 0xFF
buf[1] = val & 0xFF
device.write(buf)
@property
def bias(self):
"""Get and set the boolean state of the sensor's bias (True/False)."""
return bool(self._read_u8(_MAX31865_CONFIG_REG) & _MAX31865_CONFIG_BIAS)
def set_bias(self, val):
config = self._read_u8(_MAX31865_CONFIG_REG)
if val:
config |= _MAX31865_CONFIG_BIAS # Enable bias.
else:
config &= ~_MAX31865_CONFIG_BIAS # Disable bias.
self._write_u8(_MAX31865_CONFIG_REG, config)
@property
def auto_convert(self):
"""Get and set the boolean state of the sensor's automatic conversion
mode (True/False).
"""
return bool(self._read_u8(_MAX31865_CONFIG_REG) & _MAX31865_CONFIG_MODEAUTO)
def set_auto_convert(self, val):
config = self._read_u8(_MAX31865_CONFIG_REG)
if val:
config |= _MAX31865_CONFIG_MODEAUTO # Enable auto convert.
else:
config &= ~_MAX31865_CONFIG_MODEAUTO # Disable auto convert.
self._write_u8(_MAX31865_CONFIG_REG, config)
@property
def fault(self):
"""Get the fault state of the sensor. Use `clear_faults` to clear the
fault state. Returns a 6-tuple of boolean values which indicate if any
faults are present:
- HIGHTHRESH
- LOWTHRESH
- REFINLOW
- REFINHIGH
- RTDINLOW
- OVUV
"""
faults = self._read_u8(_MAX31865_FAULTSTAT_REG)
#pylint: disable=bad-whitespace
highthresh = bool(faults & _MAX31865_FAULT_HIGHTHRESH)
lowthresh = bool(faults & _MAX31865_FAULT_LOWTHRESH)
refinlow = bool(faults & _MAX31865_FAULT_REFINLOW)
refinhigh = bool(faults & _MAX31865_FAULT_REFINHIGH)
rtdinlow = bool(faults & _MAX31865_FAULT_RTDINLOW)
ovuv = bool(faults & _MAX31865_FAULT_OVUV)
#pylint: enable=bad-whitespace
return (highthresh, lowthresh, refinlow, refinhigh, rtdinlow, ovuv)
def clear_faults(self):
"""Clear any fault state previously detected by the sensor."""
config = self._read_u8(_MAX31865_CONFIG_REG)
config &= ~0x2C
config |= _MAX31865_CONFIG_FAULTSTAT
self._write_u8(_MAX31865_CONFIG_REG, config)
def read_rtd(self):
"""Perform a raw reading of the thermocouple and return its 15-bit
value. You'll need to manually convert this to temperature using the
nominal value of the resistance-to-digital conversion and some math. If you just want
temperature use the temperature property instead.
"""
self.clear_faults()
self.set_bias(True)
time.sleep(0.01)
config = self._read_u8(_MAX31865_CONFIG_REG)
config |= _MAX31865_CONFIG_1SHOT
self._write_u8(_MAX31865_CONFIG_REG, config)
time.sleep(0.065)
rtd = self._read_u16(_MAX31865_RTDMSB_REG)
# Remove fault bit.
rtd >>= 1
return rtd
@property
def resistance(self):
"""Read the resistance of the RTD and return its value in Ohms."""
resistance = self.read_rtd()
resistance /= 32768
resistance *= self.ref_resistor
return resistance
@property
def temperature(self):
"""Read the temperature of the sensor and return its value in degrees
Celsius.
"""
# This math originates from:
# http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
# To match the naming from the app note we tell lint to ignore the Z1-4
# naming.
# pylint: disable=invalid-name
raw_reading = self.resistance
Z1 = -_RTD_A
Z2 = _RTD_A * _RTD_A - (4 * _RTD_B)
Z3 = (4 * _RTD_B) / self.rtd_nominal
Z4 = 2 * _RTD_B
temp = Z2 + (Z3 * raw_reading)
temp = (math.sqrt(temp) + Z1) / Z4
if temp >= 0:
return temp
# Have to normalize to 100 ohms if temperure is less than 0C for the following math to work
raw_reading /= self.rtd_nominal
raw_reading *= 100
rpoly = raw_reading
temp = -242.02
temp += 2.2228 * rpoly
rpoly *= raw_reading # square
temp += 2.5859e-3 * rpoly
rpoly *= raw_reading # ^3
temp -= 4.8260e-6 * rpoly
rpoly *= raw_reading # ^4
temp -= 2.8183e-8 * rpoly
rpoly *= raw_reading # ^5
temp += 1.5243e-10 * rpoly
return temp
Kind Regards,
Sam Logan