Currently using 3 Raspberry Pi's. Each one of them should be able to collect x, y and z with an accelerometer. However a problem is occuring when I run the following script on my newest Raspberry Pi:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Example on how to read the ADXL345 accelerometer.
# Kim H. Rasmussen, 2014
import sys, math, os, spidev, datetime, ftplib
# Setup SPI
spi = spidev.SpiDev()
#spi.mode = 3 <-- Important: Do not do this! Or SPI won't work as intended, or even at all.
spi.open(0,0)
spi.mode = 3
# Read the Device ID (should be xe5)
id = spi.xfer2([128,0])
print 'Device ID (Should be 0xe5):\n'+str(hex(id[1])) + '\n'
# Read the offsets
xoffset = spi.xfer2([30 | 128,0])
yoffset = spi.xfer2([31 | 128,0])
zoffset = spi.xfer2([32 | 128,0])
accres = 2
accrate = 13
print 'Offsets: '
print xoffset[1]
print yoffset[1]
# print str(zoffset[1]) + "\n\nRead the ADXL345 every half second:"
# Initialize the ADXL345
def initadxl345():
# Enter power saving state
spi.xfer2([45, 0])
# Set data rate to 100 Hz. 15=3200, 14=1600, 13=800, 12=400, 11=200, 10=100 etc.
spi.xfer2([44, accrate])
# Enable full range (10 bits resolution) and +/- 16g 4 LSB
spi.xfer2([49, accres])
# Enable measurement
spi.xfer2([45, 8])
# Read the ADXL x-y-z axia
def readadxl345():
rx = spi.xfer2([242,0,0,0,0,0,0])
#
out = [rx[1] | (rx[2] << 8),rx[3] | (rx[4] << 8),rx[5] | (rx[6] << 8)]
# Format x-axis
if (out[0] & (1<<16 - 1 )):
out[0] = out[0] - (1<<16)
# out[0] = out[0] * 0.004 * 9.82
# Format y-axis
if (out[1] & (1<<16 - 1 )):
out[1] = out[1] - (1<<16)
# out[1] = out[1] * 0.004 * 9.82
# Format z-axis
if (out[2] & (1<<16 - 1 )):
out[2] = out[2] - (1<<16)
# out[2] = out[2] * 0.004 * 9.82
return out
# Initialize the ADXL345 accelerometer
initadxl345()
# Read the ADXL345 every half second
timetosend = 60
while(1):
with open('/proc/uptime','r') as f: # get uptime
uptime_start = float(f.readline().split()[0])
uptime_last = uptime_start
active_file_first = "S3-" + str(pow(2,accrate)*25/256) + "hz10bit" + str(accres) + 'g' + str(datetime.datetime.utcnow().strftime('%y%m%d%H%M')) $
active_file = active_file_first.replace(":", ".")
wStream = open('/var/log/sensor/' + active_file,'wb')
finalcount = 0
print "Creating " + active_file
while uptime_last < uptime_start + timetosend:
finalcount += 1
time1 = str(datetime.datetime.now().strftime('%S.%f'))
time2 = str(datetime.datetime.now().strftime('%M'))
time3 = str(datetime.datetime.now().strftime('%H'))
time4 = str(datetime.datetime.now().strftime('%d'))
time5 = str(datetime.datetime.now().strftime('%m'))
time6 = str(datetime.datetime.now().strftime('%Y'))
axia = readadxl345()
wStream.write(str(round(float(axia[0])/1024,3))+','+str(round(float(axia[1])/1024,3))+','+str(round(float(axia[2])/1024,3))+','+time1+','+ti$
# Print the reading
# print axia[0]
# print axia[1]
# print str(axia[2]) + '\n'
# elapsed = time.clock()
# current = 0
# while(current < timeout):
# current = time.clock() - elapsed
with open('/proc/uptime', 'r') as f:
uptime_last = float(f.readline().split()[0])
wStream.close()
def doftp(the_active_file):
session = ftplib.FTP('192.0.3.6','sensor3','L!ghtSp33d')
session.cwd("//datalogger//")
file = open('/var/log/sensor/' + active_file, 'rb') # file to send
session.storbinary('STOR' + active_file, file) # send the file
file.close()
session.quit
My two other Raspberry Pi's show the following when I run the script:
Device ID (Should be 0xe5):
0xe5
Offsets:
0
0
This is supposed to be the same for my 3rd Raspberry Pi regardless of how the accelerometer is positioned before I run the script.
However for some reason I get an output like this with my new Raspberry Pi:
Device ID (Should be 0xe5):
0x1
Offsets:
1
1
Sometimes it shows a complete different Device ID and offset.
All 3 Raspberry Pi have the exact same in both /etc/modules and /boot/config.txt.
When I run ls /dev/*spi* on both I get /dev/spidev0.0 /dev/spidev0.1 for all 3 Raspberry Pi's.
After exchanging MicroSD cards between the Raspberry Pi's it became clear that the issue has nothing to do with the hardware. It comes down to the software.
Does anyone in here have an idea of how I fix this issue? The fact that it isn't showing proper Device ID and offsets just makes the data I collect messed up and useless.
Related
I am attempting to read data from a load cell panel which is configured for Modbus RTU protocol. The goal of the program is to log data, I will link the entire program below, but the setup is where I am having issues. I have gotten the module to respond with data, and it is wired in the only configuration which allows communication over USB, so I assume this is done correctly.
The response, which I am saving as 'load' which is being returned to me is:
[[ 0* 2* 3245 0 -28 -1 1000 0]]
*The stars represent the parts of the response which look fully incorrect, based on the expected return values.
This seems to be incorrect, the response I expect is characterized by:
[Slave Address, Function, Byte Count, Data Hi, Data Lo, Data Hi, Data Lo, Error Check Lo, Error Check Hi]
a total of 9 bytes (72 bits). So, I would expect a response to look more like this:
[1*, 4*, 4, 00, 06, 00, 05, DB, 86]
*The stars represent the parts of the response which look fully incorrect, based on the expected return values.
**Expected response taken from: https://www.modbustools.com/modbus.html#function04
I would also expect the values of the Data Bytes to change as I add or remove load from the call, as the panel meter is reading correctly, but the response does not change as the program loops. Does anyone with MinimalModbus experiance have any guesses as to what might be going wrong to get this return?
This is the code of interest:
import minimalmodbus
import serial
import numpy as np
units = "lb."
comPort = "COM6"
baudRate = 9600
functionImplemented = 4
minimalmodbus.slaveaddress = 1
minimalmodbus.registeraddress = 3 #1, 2, 3 for this application
instrument = minimalmodbus.Instrument(comPort, minimalmodbus.slaveaddress)
instrument.serial.port = comPort
instrument.serial.baudrate = baudRate
instrument.serial.parity = serial.PARITY_EVEN
instrument.serial.bytesize = 8
instrument.serial.stopbits = 1
instrument.mode = minimalmodbus.MODE_RTU
instrument.serial.timeout = 2
n=0
run=True
while run is True:
#record new temperature values WHEN UPDATED?
load=np.array([[1,1,1,1,1,1,1,1]])
for x in range(8):
i=x+1
minimalmodbus.registeraddress=i
load[0,x]=instrument.read_register(minimalmodbus.registeraddress,
number_of_decimals=0, functioncode=functionImplemented, signed=True)
print("load ("+str(n)+"): " + str(load))
n = n + 1
This is the full program, if anyone's interested, but the part that is malfunctioning is what is listed above.:
##author: Jack M
import time
import minimalmodbus
import serial
import numpy as np
import matplotlib.pyplot as plt
units = "lb."
comPort = "COM6"
baudRate = 9600
functionImplemented = 4
minimalmodbus.slaveaddress = 1
minimalmodbus.registeraddress = 3 #1, 2, 3 for this application
instrument = minimalmodbus.Instrument(comPort, minimalmodbus.slaveaddress)
instrument.serial.port = comPort
instrument.serial.baudrate = baudRate
instrument.serial.parity = serial.PARITY_EVEN
instrument.serial.bytesize = 8
instrument.serial.stopbits = 1
instrument.mode = minimalmodbus.MODE_RTU
instrument.serial.timeout = 2
stime = np.array([[0]])
sload = np.array([[1,1,1,1,1,1,1,1],[2,2,2,2,2,2,2,2]])
print("sload: " + str(sload))
n=0
run=True
while run is True:
#record new temperature values WHEN UPDATED?
load=np.array([[1,1,1,1,1,1,1,1]])
for x in range(8):
i=x+1
minimalmodbus.registeraddress=i
load[0,x]=instrument.read_register(minimalmodbus.registeraddress,
number_of_decimals=0, functioncode=functionImplemented, signed=True)
print("load ("+str(n)+"): " + str(load))
sload=np.append(sload,load,axis=0)
n = n + 1
newTime = [[time.time()]]
#store the input values
stime=np.append(stime,newTime, axis=0)
plt.plot(stime,sload,'ro')
plt.title("Load (lbf) vs. Time (s)")
plt.xlabel("Time (s)")
plt.ylabel("Load (Lbf)")
plt.show()
print("Max: "+ str(np.max(sload)))
Im trying to establish my own Raspy-Installation with a light-control.
I am trying to get a script-code working, to enable the light-control-service.
I am getting a really simple error message, but i cant fix it on my own:
Traceback (most recent call last):
File "test.py", line 13, in <module>
bus.write_byte_data(0x39, 0x00 | 0x80, 0x03)
IOError: [Errno 5] Input/output error
I just want to show you the complete code. Is anyone able to help me? :)
from os import system
system("sudo killall pigpiod")
system("sudo pigpiod")
import RPi.GPIO as GPIO
import time
import pigpio
import smbus
bus = smbus.SMBus(1)
#Lichtsensor (Adresse 0x39) initialisieren
#Power On Mode
bus.write_byte_data(0x39, 0x00 | 0x80, 0x03)
bus.write_byte_data(0x39, 0x01 | 0x80, 0x02)
#kurze Pause
time.sleep(0.5)
#Lichtsensor auslesen
data = bus.read_i2c_block_data(0x39, 0x0c | 0x80, 2)
data1 = bus.read_i2c_block_data(0x39, 0x0e | 0x80, 2)
#Lichtdaten aufbereiten
ch0 = data[1] * 256 + data[0]
ch1 = data1[1] * 256 + data1[0]
#Lichtdaten ausgeben
print "Volles Spektrum (Infrarot+sichtbar) : %d lux" %ch0
print "Infrarot-Wert: %d lux" %ch1
print "sichtbares Licht-Wert : %d lux" %(ch0 - ch1)
#GPIO ports setzen und zuweisen
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
red = 17
green = 27
blue = 22
PIR = 5
GPIO.setup(red, GPIO.OUT)
GPIO.setup(green, GPIO.OUT)
GPIO.setup(blue, GPIO.OUT)
GPIO.setup(PIR, GPIO.IN)
pi = pigpio.pi()
#Variablen definieren
pi.set_PWM_dutycycle(red, 0)
pi.set_PWM_dutycycle(green, 0)
pi.set_PWM_dutycycle(blue, 0)
fade_in_delay = .1
fade_out_delay = .1
delay_time = 5
mycolor = blue
brightness = 200
min_light = 9
moment = 0
RUNNING = True
#Script starten
try:
while RUNNING:
data = bus.read_i2c_block_data(0x39, 0x0c | 0x80, 2)
data1 = bus.read_i2c_block_data(0x39, 0x0e | 0x80, 2)
ch0 = data[1] * 256 + data[0]
ch1 = data1[1] * 256 + data1[0]
light = ch0 - ch1
print "sichtbares Licht-Wert : %d lux" %(light)
if pi.read(PIR):
print "PIR = ON"
else:
print "PIR = OFF"
if moment > 1:
start = moment
else:
start = 0
if (pi.read(PIR) & (light < min_light)):
for x in range(start,brightness):
pi.set_PWM_dutycycle(mycolor, x)
time.sleep(fade_in_delay)
moment = x
while (pi.read(PIR) & (light < min_light)):
time.sleep(delay_time)
if not (pi.read(PIR) & (moment > 0)):
for x in range(brightness, 0, -1):
pi.set_PWM_dutycycle(mycolor, x)
time.sleep(fade_out_delay)
moment = 0
except KeyboardInterrupt:
RUNNING = False
I couldnt transform the usual tools to fix the problem i got by using google. Im also just a beginner in writing own python-scripts. Normally I´m looking for existing codes (like this) and get it done for my own use case.
I try to use a AD5270, 20KOhm SPI potentiometer for a personal project with my Raspberry Pi 3B+. I translate some Arduino libraries code to Python language but it looks like it won't work. I can't test if the potentiometer is good value configured so I read the resistor value and always get 0 from SPI register.
Problem : I don't know if my writing is well done because I can't probe the resistor. To know if it works, I read the register and always receive 0x00. Writing and/or reading won't work.
Expect : reading what I have written.
Hardware setup :
!SYNC = CE0 = PIN24
DIN = MISO = PIN19
SDO = MOSI = PIN21
SLCK = SCLK = PIN23
with 1uF ext capacitor and 3V3 supply (from Raspberry).
The datasheet of the AD5270 is available here.
Minimalist code following the datasheet that won't work :
spi = spidev.SpiDev()
spi.open(spi_bus, spi_device_select)
spi.max_speed_hz = 50000 # Datasheet p7
spi.mode = 1 # CPOL = 0, CPHA = 1 (Datasheet p7)
# Datasheet example
data = [0x1C, 0x03]
r = spi.xfer(data)
print(r)
data = [0x05, 0x00]
r = spi.xfer(data)
print(r)
data = [0x08, 0x00]
r = spi.xfer(data)
print(r)
data = [0xC0, 0x00]
r = spi.xfer(data)
print(r)
From your hardware setup:
DIN = MISO = PIN21 (through 10 Ohm resistor)
SDO = MOSI = PIN19 (through 10 Ohm resistor)
DIN is input to AD5270, and therefore output of your RPI, so it should be MOSI. Same problem for SDO.
I finally got the tricks. Don't forget to add a pullup on SDO line and configure Spidev for the AD5270. This code work quite well :
# SPI test code for AD5270BRMZ-20
import time
import spidev
spi_bus = 0 # SPI0
spi_device_select = 0 # CE0
spi = spidev.SpiDev()
spi.open(spi_bus, spi_device_select)
spi.max_speed_hz = 50000 # Datasheet p7
spi.mode = 1 # CPOL = 0, CPHA = 1 (Datasheet p7)
spi.lsbfirst = False # Datasheet p18
MAX_RESISTANCE = 20000.0
WRITE_CTRL_REG = 0x1C
READ_CTRL_REG = 0x20
WRITE_RDAC = 0x04
READ_RDAC = 0x08
RDAC_WRITE_PROTECT = 0x02
def AD5270_CalcRDAC(resistance):
return int((resistance / MAX_RESISTANCE) * 1024.0)
def AD5270_ReadReg(command):
data = [(command & 0x3C), 0]
r = spi.xfer2(data)
data = [0x00, 0x00]
r2 = spi.xfer2(data)
result = r2[0]
result = (result << 8) | r2[1]
return result
def AD5270_WriteReg(command, value):
ui16Command = (command & 0x3C) << 8 | (value & 0x3FF)
data = [(ui16Command >> 8) & 0xFF, ui16Command & 0xFF]
spi.xfer2(data)
def AD5270_ReadRDAC():
RDAC_val = AD5270_ReadReg(READ_RDAC)
RDAC_val &= 0x03FF
return ((RDAC_val) * MAX_RESISTANCE) / 1024.0
def AD5270_WriteRDAC(resistance):
RDAC_val = AD5270_CalcRDAC(resistance)
spi.xfer2([WRITE_CTRL_REG, RDAC_WRITE_PROTECT])
AD5270_WriteReg(WRITE_RDAC, RDAC_val);
return ((RDAC_val * MAX_RESISTANCE) / 1024.0)
while(1):
AD5270_WriteRDAC(10000.0) # Write 10KOhm
print(AD5270_ReadRDAC())
time.sleep(1)
spi.close()
I am using the following code to get the temperature of a PT100 (3-wire) and a PT1000 (2-wire) simultaneously on my raspberry.
According to https://cdn-learn.adafruit.com/downloads/pdf/adafruit-max31865-rtd-pt100-amplifier.pdf my wiring is correct.
from Max31865 import Max31865
maxGarraum = Max31865()
maxGarraum.initPt100_3WireSensor(26, True)
maxFleisch = Max31865()
maxFleisch.initPt1000_2WireSensor(24, True)
while True:
maxGarraum.getCurrentTemp()
time.sleep(1)
My Max31865.py looks like the following:
import time, math
import RPi.GPIO as GPIO
# import numpy
class Max31865():
def initPt1000_2WireSensor(self, iCsPin):
self.csPin = iCsPin
# Fleischsensor Pt1000 (2-wire)
self.registerCode = 0xA2
self.setupGPIO()
def initPt100_3WireSensor(self, iCsPin):
self.csPin = iCsPin
# Garraumsensor Pt100 (3-wire)
self.registerCode = 0xB2
self.setupGPIO()
def setupGPIO(self):
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.csPin, GPIO.OUT)
GPIO.setup(self.misoPin, GPIO.IN)
GPIO.setup(self.mosiPin, GPIO.OUT)
GPIO.setup(self.clkPin, GPIO.OUT)
GPIO.output(self.csPin, GPIO.HIGH)
GPIO.output(self.clkPin, GPIO.LOW)
GPIO.output(self.mosiPin, GPIO.LOW)
def getCurrentTemp(self):is
# b10000000 = 0x80
# 0x8x to specify 'write register value'
# 0xx0 to specify 'configuration register'
#
# 0b10110010 = 0xB2
# Config Register - https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
# ---------------
# bit 7: Vbias -> 1 (ON)
# bit 6: Conversion Mode -> 0 (MANUAL)
# bit 5: 1-shot ->1 (ON)
# bit 4: 3-wire select -> 1 (3 wire config) (0 for 2-/4-wire)
# bit 3-2: fault detection cycle -> 0 (none)
# bit 1: fault status clear -> 1 (clear any fault)
# bit 0: 50/60 Hz filter select -> 0 (60Hz)
#
# 0b11010010 or 0xD2 for continuous auto conversion
# at 60Hz (faster conversion)
# one shot
self.writeRegister(0, self.registerCode)
# conversion time is less than 100ms
time.sleep(.1) # give it 100ms for conversion
# read all registers
out = self.readRegisters(0, 8)
conf_reg = out[0]
#print("Config register byte: %x" % conf_reg)
[rtd_msb, rtd_lsb] = [out[1], out[2]]
rtd_ADC_Code = ((rtd_msb << 8) | rtd_lsb) >> 1
temp = self.calcTemperature(rtd_ADC_Code)
"""
# High fault threshold
[hft_msb, hft_lsb] = [out[3], out[4]]
hft = ((hft_msb << 8) | hft_lsb) >> 1
# Low fault threshold
[lft_msb, lft_lsb] = [out[5], out[6]]
lft = ((lft_msb << 8) | lft_lsb) >> 1
print ("High fault threshold: ", hft , " --- Low fault threshold: " , lft)
"""
status = out[7]
# 10 Mohm resistor is on breakout board to help
# detect cable faults
# bit 7: RTD High Threshold / cable fault open
# bit 6: RTD Low Threshold / cable fault short
# bit 5: REFIN- > 0.85 x VBias -> must be requested
# bit 4: REFIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 3: RTDIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 2: Overvoltage / undervoltage fault
# bits 1,0 don't care
# print "Status byte: %x" % status
if ((status & 0x80) == 1):
raise FaultError("High threshold limit (Cable fault/open)")
if ((status & 0x40) == 1):
raise FaultError("Low threshold limit (Cable fault/short)")
if ((status & 0x04) == 1):
raise FaultError("Overvoltage or Undervoltage Error")
return temp
def writeRegister(self, regNum, dataByte):
GPIO.output(self.csPin, GPIO.LOW)
# 0x8x to specify 'write register value'
addressByte = 0x80 | regNum;
# first byte is address byte
#print("Cs-Pin: ", self.csPin, "Addresse: ", addressByte)
self.sendByte(addressByte)
# the rest are data bytes
self.sendByte(dataByte)
GPIO.output(self.csPin, GPIO.HIGH)
def readRegisters(self, regNumStart, numRegisters):
out = []
GPIO.output(self.csPin, GPIO.LOW)
# 0x to specify 'read register value'
self.sendByte(regNumStart)
for byte in range(numRegisters):
data = self.recvByte()
out.append(data)
GPIO.output(self.csPin, GPIO.HIGH)
return out
def sendByte(self, byte):
for bit in range(8):
GPIO.output(self.clkPin, GPIO.HIGH)
if (byte & 0x80):
GPIO.output(self.mosiPin, GPIO.HIGH)
else:
GPIO.output(self.mosiPin, GPIO.LOW)
byte <<= 1
GPIO.output(self.clkPin, GPIO.LOW)
def recvByte(self):
byte = 0x00
for bit in range(8):
GPIO.output(self.clkPin, GPIO.HIGH)
byte <<= 1
if GPIO.input(self.misoPin):
byte |= 0x1
GPIO.output(self.clkPin, GPIO.LOW)
return byte
def calcTemperature(self, RTD_ADC_Code):
global temp
R_REF = 0.0 # Reference Resistor
Res0 = 0.0; # Resistance at 0 degC for 400ohm R_Ref
a = 0.0
b = 0.0
c = 0.0
if (self.registerCode == 0xA2):
############# PT1000 #############
R_REF = 4300.0 # Reference Resistor
Res0 = 1000.0; # Resistance at 0 degC for 430ohm R_Ref
a = .00381
b = -.000000602
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.000000000006
# c = 0 # for 0 <= T <= 850 (degC)
else:
############# PT100 #############
R_REF = 430.0 # Reference Resistor
Res0 = 100.0; # Resistance at 0 degC for 430ohm R_Ref
a = .00390830
b = -.000000577500
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.00000000000418301
# c = 0 # for 0 <= T <= 850 (degC)
Res_RTD = (RTD_ADC_Code * R_REF) / 32768.0 # PT1000 Resistance
#print("CS-Pin: " , self.csPin, " --- ADC-Value: ", RTD_ADC_Code , " --- Resistance: ", round(Res_RTD, 2) , " Ohms")
# Callendar-Van Dusen equation
# Res_RTD = Res0 * (1 + a*T + b*T**2 + c*(T-100)*T**3)
# Res_RTD = Res0 + a*Res0*T + b*Res0*T**2 # c = 0
# (c*Res0)T**4 - (c*Res0)*100*T**3
# + (b*Res0)*T**2 + (a*Res0)*T + (Res0 - Res_RTD) = 0
#
# quadratic formula:
# for 0 <= T <= 850 (degC)
temp = -(a * Res0) + math.sqrt(a * a * Res0 * Res0 - 4 * (b * Res0) * (Res0 - Res_RTD))
temp = round(temp / (2 * (b * Res0)), 2)
# removing numpy.roots will greatly speed things up
# temp_C_numpy = numpy.roots([c*Res0, -c*Res0*100, b*Res0, a*Res0, (Res0 - Res_RTD)])
# temp_C_numpy = abs(temp_C_numpy[-1])
# print "Solving Full Callendar-Van Dusen using numpy: %f" % temp_C_numpy
if (temp < 0): # use straight line approximation if less than 0
# Can also use python lib numpy to solve cubic
# Should never get here in this application
temp = (RTD_ADC_Code / 32) - 256
print ("CSPin " , self.csPin, " - ADC: ", RTD_ADC_Code , " - Resistance: ", round(Res_RTD, 2) , " Ohms - Temp: " , temp)
return temp
##############################################################################################################################
# Programmstart #
###############################################################################################################################
csPin = 0
misoPin = 21
mosiPin = 19
clkPin = 23
registerCode = 0
# BOARD:21,19,23
# BCM: 9,10,11
class FaultError(Exception):
pass
The problem is that I get no data for the PT100-rtd - only for the PT1000.
The wiring with my raspberry must be correct, because I also adapted my code to test the wiring with two PT1000-rtd and it works.
I think that my problem is somewhere at "getCurrentTemp(self)". Maybe at the readRegister(..) and writeRegister(..) with the "regNum" and "regNumStart".
Any idea?
It looks like you are trying to use the circuitPython code.
Look at this location for the latest version of this code.
Follow the instructions and ensure that you have all required
dependencies met on your platform.
Look here for their simple example of how to test.
Good Luck!
Using github and a tutorial I adapt the given Code to read the temperature on my raspberry using an PT1000 sensor.
I am using the mode "GPIO.BOARD", adapt the "writeRegister(0, 0xB2)" to "writeRegister(0, 0xA2)" and I also changed the programstart.
Here's my current code:
#!/usr/bin/python
# The MIT License (MIT)
#
# Copyright (c) 2015 Stephen P. Smith
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import time, math
import RPi.GPIO as GPIO
# import numpy
"""Reading Temperature from the MAX31865 with GPIO using
the Raspberry Pi. Any pins can be used.
Numpy can be used to completely solve the Callendar-Van Dusen equation
but it slows the temp reading down. I commented it out in the code.
Both the quadratic formula using Callendar-Van Dusen equation (ignoring the
3rd and 4th degree parts of the polynomial) and the straight line approx.
temperature is calculated with the quadratic formula one being the most accurate.
"""
def setupGPIO():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(csPin, GPIO.OUT)
GPIO.setup(misoPin, GPIO.IN)
GPIO.setup(mosiPin, GPIO.OUT)
GPIO.setup(clkPin, GPIO.OUT)
GPIO.output(csPin, GPIO.HIGH)
GPIO.output(clkPin, GPIO.LOW)
GPIO.output(mosiPin, GPIO.LOW)
def readTemp():
# b10000000 = 0x80
# 0x8x to specify 'write register value'
# 0xx0 to specify 'configuration register'
#
# 0b10110010 = 0xB2
# Config Register - https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
# ---------------
# bit 7: Vbias -> 1 (ON)
# bit 6: Conversion Mode -> 0 (MANUAL)
# bit 5: 1-shot ->1 (ON)
# bit 4: 3-wire select -> 1 (3 wire config) (0 for 2-/4-wire)
# bit 3-2: fault detection cycle -> 0 (none)
# bit 1: fault status clear -> 1 (clear any fault)
# bit 0: 50/60 Hz filter select -> 0 (60Hz)
#
# 0b11010010 or 0xD2 for continuous auto conversion
# at 60Hz (faster conversion)
# one shot
writeRegister(0, 0xA2)
# conversion time is less than 100ms
time.sleep(.1) # give it 100ms for conversion
# read all registers
out = readRegisters(0, 8)
conf_reg = out[0]
print("Config register byte: %x" % conf_reg , " [HEX]")
[rtd_msb, rtd_lsb] = [out[1], out[2]]
rtd_ADC_Code = ((rtd_msb << 8) | rtd_lsb) >> 1
temp_C = calcPT1000Temp(rtd_ADC_Code)
# High fault threshold
[hft_msb, hft_lsb] = [out[3], out[4]]
hft = ((hft_msb << 8) | hft_lsb) >> 1
# Low fault threshold
[lft_msb, lft_lsb] = [out[5], out[6]]
lft = ((lft_msb << 8) | lft_lsb) >> 1
print ("High fault threshold: ", hft , " --- Low fault threshold: " , lft)
status = out[7]
#
# 10 Mohm resistor is on breakout board to help
# detect cable faults
# bit 7: RTD High Threshold / cable fault open
# bit 6: RTD Low Threshold / cable fault short
# bit 5: REFIN- > 0.85 x VBias -> must be requested
# bit 4: REFIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 3: RTDIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 2: Overvoltage / undervoltage fault
# bits 1,0 don't care
# print "Status byte: %x" % status
if ((status & 0x80) == 1):
raise FaultError("High threshold limit (Cable fault/open)")
if ((status & 0x40) == 1):
raise FaultError("Low threshold limit (Cable fault/short)")
if ((status & 0x04) == 1):
raise FaultError("Overvoltage or Undervoltage Error")
def writeRegister(regNum, dataByte):
GPIO.output(csPin, GPIO.LOW)
# 0x8x to specify 'write register value'
addressByte = 0x80 | regNum;
# first byte is address byte
sendByte(addressByte)
# the rest are data bytes
sendByte(dataByte)
GPIO.output(csPin, GPIO.HIGH)
def readRegisters(regNumStart, numRegisters):
out = []
GPIO.output(csPin, GPIO.LOW)
# 0x to specify 'read register value'
sendByte(regNumStart)
for byte in range(numRegisters):
data = recvByte()
out.append(data)
GPIO.output(csPin, GPIO.HIGH)
return out
def sendByte(byte):
for bit in range(8):
GPIO.output(clkPin, GPIO.HIGH)
if (byte & 0x80):
GPIO.output(mosiPin, GPIO.HIGH)
else:
GPIO.output(mosiPin, GPIO.LOW)
byte <<= 1
GPIO.output(clkPin, GPIO.LOW)
def recvByte():
byte = 0x00
for bit in range(8):
GPIO.output(clkPin, GPIO.HIGH)
byte <<= 1
if GPIO.input(misoPin):
byte |= 0x1
GPIO.output(clkPin, GPIO.LOW)
return byte
def calcPT1000Temp(RTD_ADC_Code):
############# PT1000 #############
R_REF = 400.0 # Reference Resistor
Res0 = 1000.0; # Resistance at 0 degC for 400ohm R_Ref
a = .00381
b = -.000000602
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.000000000006
# c = 0 # for 0 <= T <= 850 (degC)
# c = 0 # for 0 <= T <= 850 (degC)
"""
############# PT100 #############
R_REF = 400.0 # Reference Resistor
Res0 = 100.0; # Resistance at 0 degC for 400ohm R_Ref
a = .00390830
b = -.000000577500
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.00000000000418301
# c = 0 # for 0 <= T <= 850 (degC)
"""
Res_RTD = (RTD_ADC_Code * R_REF) / 32768.0 # PT1000 Resistance
Res_RTD = round(Res_RTD, 3)
print("RTD ADC Code: ", RTD_ADC_Code , " --- PT1000 Resistance: ", Res_RTD , " Ohms")
# Callendar-Van Dusen equation
# Res_RTD = Res0 * (1 + a*T + b*T**2 + c*(T-100)*T**3)
# Res_RTD = Res0 + a*Res0*T + b*Res0*T**2 # c = 0
# (c*Res0)T**4 - (c*Res0)*100*T**3
# + (b*Res0)*T**2 + (a*Res0)*T + (Res0 - Res_RTD) = 0
#
# quadratic formula:
# for 0 <= T <= 850 (degC)
temp_C = -(a * Res0) + math.sqrt(a * a * Res0 * Res0 - 4 * (b * Res0) * (Res0 - Res_RTD))
temp_C = temp_C / (2 * (b * Res0))
temp_C_line = (RTD_ADC_Code / 32.0) - 256.0
# removing numpy.roots will greatly speed things up
# temp_C_numpy = numpy.roots([c*Res0, -c*Res0*100, b*Res0, a*Res0, (Res0 - Res_RTD)])
# temp_C_numpy = abs(temp_C_numpy[-1])
print ("Straight Line Approx. Temp: ", temp_C_line , " --- Callendar-Van Dusen Temp (degC > 0): " , temp_C)
# print "Solving Full Callendar-Van Dusen using numpy: %f" % temp_C_numpy
if (temp_C < 0): # use straight line approximation if less than 0
# Can also use python lib numpy to solve cubic
# Should never get here in this application
temp_C = (RTD_ADC_Code / 32) - 256
return temp_C
###############################################################################################################################
# Programstart #
###############################################################################################################################
# Pin-Setup: (BCM: 8, 9, 10, 11)
csPin = 24
misoPin = 21
mosiPin = 19
clkPin = 23
setupGPIO()
while True:
tempC = readTemp()
time.sleep(1)
GPIO.cleanup()
class FaultError(Exception):
pass
The output is the following:
Config register byte: 80 [HEX]
RTD ADC Code: 1299 --- PT1000 Resistance: 15.857 Ohms
Straight Line Approx. Temp: -215.40625 --- Callendar-Van Dusen Temp (degC > 0): -248.54456939832218
The values of the "RTD ADC Code" and the "PT1000 Resistance" increase continuously.
I dont know whats the reason for this wrong behavior. I also tried different wiring-settings - Currently is use this one.