Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max3185x update #34

Closed
wants to merge 12 commits into from
6 changes: 6 additions & 0 deletions firmware/ini/wideband_dual.ini
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ AFR1_heater = scalar, U08, 93, "", 1, 0
EGT0_temp = scalar, F32, 96, "C", 1, 0
EGT0_coldJunction = scalar, F32, 100, "C", 1, 0
EGT0_state = scalar, U08, 104, "", 1, 0
EGT0_commErrors = scalar, U32, 108, "n", 1, 0

; EGT1
EGT1_temp = scalar, F32, 112, "C", 1, 0
EGT1_coldJunction = scalar, F32, 116, "C", 1, 0
EGT1_state = scalar, U08, 120, "", 1, 0
EGT1_commErrors = scalar, U32, 124, "n", 1, 0

; TODO: something is wrong with these
Aux0InputSig = { (Aux0InputSel == 0) ? AFR0_lambda : ((Aux0InputSel == 1) ? AFR1_lambda : ((Aux0InputSel == 2) ? EGT0_temp : EGT1_temp)) }
Expand Down Expand Up @@ -205,13 +207,15 @@ gaugeCategory = EGT channel 0
EGT0_Gauge = EGT0_temp, "0: EGT", "C", 0.0, 1600.0, 100.0, 250.0, 900.0, 1000.0, 0, 0
EGT0_ColdJunctionGauge = EGT0_coldJunction, "0: EGT CJ", "C", 0.0, 130.0, -55.0, -20.0, 95.0, 105.0, 1, 1
EGT0_StateGauge = EGT0_state, "0: EGT state", "", 0.0, 5.0, 0.0, 0.0, 0.5, 0.5, 0, 0
EGT0_CommErrorsGauge = EGT0_commErrors,"0: EGT comm errors", "", 0.0, 10, 0.0, 0.0, 1, 1, 0, 0

; EGT1
gaugeCategory = EGT channel 1
; Name = Channel, Title, Units, Lo, Hi, LoD, LoW, HiW, HiD, vd, ld, Active
EGT1_Gauge = EGT1_temp, "1: EGT", "C", 0.0, 1600.0, 100.0, 250.0, 900.0, 1000.0, 0, 0
EGT1_ColdJunctionGauge = EGT1_coldJunction, "1: EGT CJ", "C", 0.0, 130.0, -55.0, -20.0, 95.0, 105.0, 1, 1
EGT1_StateGauge = EGT1_state, "1: EGT state", "", 0.0, 5.0, 0.0, 0.0, 0.5, 0.5, 0, 0
EGT1_CommErrorsGauge = EGT1_commErrors,"1: EGT comm errors", "", 0.0, 10, 0.0, 0.0, 1, 1, 0, 0

; AUX outputs
Aux0InputGauge = { (Aux0InputSel == 0) ? AFR0_AfrGauge : ((Aux0InputSel == 1) ? AFR1_AfrGauge : ((Aux0InputSel == 2) ? EGT0_Gauge : EGT1_Gauge)) }
Expand Down Expand Up @@ -280,11 +284,13 @@ entry = AFR1_esr, "1: ESR", float, "%.1f"
entry = EGT0_temp, "EGT 0: EGT", int, "%d"
entry = EGT0_coldJunction, "EGT 0: CJ", int, "%d"
entry = EGT0_state, "EGT 0: State", int, "%d"
entry = EGT0_commErrors, "EGT 0: comm errors", int, "%d"

; EGT1
entry = EGT1_temp, "EGT 1: EGT", int, "%d"
entry = EGT1_coldJunction, "EGT 1: CJ", int, "%d"
entry = EGT1_state, "EGT 1: State", int, "%d"
entry = EGT1_commErrors, "EGT 1: comm errors", int, "%d"

[Menu]

Expand Down
268 changes: 158 additions & 110 deletions firmware/max3185x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#if (EGT_CHANNELS > 0)

static SPIConfig spi_config[2] =
static const SPIConfig spi_config[EGT_CHANNELS] =
{
{
.circular = false,
Expand Down Expand Up @@ -43,11 +43,11 @@ static SPIConfig spi_config[2] =
}
};

static Max3185x instances[] = {&spi_config[0], &spi_config[1]};
static Max3185x instances[EGT_CHANNELS] = {Max3185x(&spi_config[0]), Max3185x(&spi_config[1])};

static Max3185xThread EgtThread(instances);

int Max3185x::spi_txrx(uint8_t tx[], uint8_t rx[], size_t n)
int Max3185x::spi_txrx(const uint8_t tx[], uint8_t rx[], size_t n)
{
/* Acquire ownership of the bus. */
spiAcquireBus(EGT_SPI_DRIVER);
Expand All @@ -58,6 +58,8 @@ int Max3185x::spi_txrx(uint8_t tx[], uint8_t rx[], size_t n)
spiExchange(EGT_SPI_DRIVER, n, tx, rx);
/* Slave Select de-assertion. */
spiUnselect(EGT_SPI_DRIVER);
/* Bus deinit */
spiStop(EGT_SPI_DRIVER);
/* Ownership release. */
spiReleaseBus(EGT_SPI_DRIVER);

Expand Down Expand Up @@ -85,152 +87,198 @@ int Max3185x::spi_rx32(uint32_t *data)
return 0;
}

int Max3185x::detect()
// bits D17 and D3 are always expected to be zero
#define MAX31855_RESERVED_BITS 0x20008

Max3185xType Max3185x::detect()
{
int ret;
uint8_t rx[4];
/* read MASK, CJHF, CJLF */
uint8_t tx[4] = {0x02, 0x00, 0x00, 0x00};
uint32_t data;
uint8_t tx[4];

/* try to apply settings to max31956 and then read back settings */
// Wr, register 0x00
tx[0] = 0x00 | BIT(7);
// CR0: 50Hz mode
// Change the notch frequency only while in the "Normally Off" mode - not in the Automatic
tx[1] = BIT(0);
// CR1: 4 samples average, K type
// The Thermocouple Voltage Conversion Averaging Mode settings should not be changed while
// conversions are taking place.
tx[2] = (2 << 4) | (3 << 0);

// Stop any conversion
ret = spi_txrx(tx, rx, 2);
if (ret) {
return UNKNOWN_TYPE;
}

int ret = spi_txrx(tx, rx, 4);
if (ret)
return ret;
data = (rx[0] << 24) |
(rx[1] << 16) |
(rx[2] << 8) |
(rx[3] << 0);
/* MASK, CJHF, CJLF defaults: 0xff, 0x7f, 0xc0 */
if ((data & 0x00ffffff) == 0x00ff7fc0) {
/* configure */
/* CR0: 50 Hz mode
* Change the notch frequency only while in the "Normally Off" mode - not in the Automatic
* Conversion mode.*/
tx[0] = 0x80;
tx[1] = 0x01;
spi_txrx(tx, rx, 2);
/* CR0: Automatic Conversion mode, OCFAULT = 2, 50Hz mode */
tx[1] = BIT(7) | BIT(0) | 2 << 4;
/* CR1: 4 samples average, K type */
tx[2] = (2 << 4) | (3 << 0);
spi_txrx(tx, rx, 3);
type = MAX31856_TYPE;
return 0;
// Apply notch frequency and averaging
ret = spi_txrx(tx, rx, 3);
if (ret) {
return UNKNOWN_TYPE;
}

// Start Automatic Conversion mode
// CR0: Automatic Conversion mode, OCFAULT = 2, 50Hz mode
tx[1] = BIT(7) | BIT(0) | (2 << 4);
// CR1: 4 samples average, K type
tx[2] = (2 << 4) | (3 << 0);
ret = spi_txrx(tx, rx, 3);
if (ret) {
return UNKNOWN_TYPE;
}
if (data != 0xffffffff) {
type = MAX31855_TYPE;
return 0;

/* Now readback settings */
tx[0] = 0x00;
ret = spi_txrx(tx, rx, 4);
if ((rx[1] == tx[1]) && (rx[2] == tx[2])) {
return MAX31856_TYPE;
}

/* in case of max31855 we get standart reply with few reserved, always zero bits */
uint32_t data = (rx[0] << 24) |
(rx[1] << 16) |
(rx[2] << 8) |
(rx[3] << 0);

/* MISO is constantly low or high */
if ((data == 0xffffffff) || (data == 0x0)) {
return UNKNOWN_TYPE;
}

if ((data & MAX31855_RESERVED_BITS) == 0x0) {
return MAX31855_TYPE;
}

livedata.state = MAX3185X_NO_REPLY;
type = UNKNOWN_TYPE;
return -1;

return UNKNOWN_TYPE;
}

int Max3185x::readPacket31855()
Max3185xState Max3185x::readPacket31855()
{
uint32_t data;

#define MAX33855_FAULT_BIT BIT(16)
#define MAX33855_OPEN_BIT BIT(0)
#define MAX33855_GND_BIT BIT(1)
#define MAX33855_VCC_BIT BIT(2)

int ret = spi_rx32(&data);

/* TODO: also check for 0x00000000? */
if ((ret) || (data == 0xffffffff)) {
livedata.state = MAX3185X_NO_REPLY;

ret = -1;
} else if (data & BIT(16)) {
if (data & BIT(0)) {
livedata.state = MAX3185X_OPEN_CIRCUIT;
} else if (data & BIT(1)) {
livedata.state = MAX3185X_SHORT_TO_GND;
} else if (data & BIT(2)) {
livedata.state = MAX3185X_SHORT_TO_VCC;
if ((ret) ||
((data & MAX31855_RESERVED_BITS) != 0) ||
(data == 0x0) ||
(data == 0xffffffff)) {
return MAX3185X_NO_REPLY;
} else if (data & MAX33855_FAULT_BIT) {
if (data & MAX33855_OPEN_BIT) {
return MAX3185X_OPEN_CIRCUIT;
} else if (data & MAX33855_GND_BIT) {
return MAX3185X_SHORT_TO_GND;
} else if (data & MAX33855_VCC_BIT) {
return MAX3185X_SHORT_TO_VCC;
}

ret = -1;
}

if (ret) {
coldJunctionTemperature = NAN;
livedata.coldJunctionTemperature = 0;
temperature = NAN;
livedata.temperature = 0;
} else {
/* D[15:4] */
int16_t tmp = (data >> 4) & 0xfff;
/* extend sign */
tmp = tmp << 4;
tmp = tmp >> 4; /* shifting right signed is not a good idea */
coldJunctionTemperature = (float)tmp * 0.0625;

/* D[31:18] */
tmp = (data >> 18) & 0x3fff;
/* extend sign */
tmp = tmp << 2;
tmp = tmp >> 2; /* shifting right signed is not a good idea */
temperature = (float) tmp * 0.25;

/* update livedata: float to int */
livedata.coldJunctionTemperature = coldJunctionTemperature;
livedata.temperature = temperature;

livedata.state = MAX3185X_OK;
}

return ret;
/* D[15:4] */
int16_t tmp = (data >> 4) & 0xfff;
/* extend sign */
tmp = tmp << 4;
tmp = tmp >> 4; /* shifting right signed is not a good idea */
coldJunctionTemperature = (float)tmp * 0.0625;

/* D[31:18] */
tmp = (data >> 18) & 0x3fff;
/* extend sign */
tmp = tmp << 2;
tmp = tmp >> 2; /* shifting right signed is not a good idea */
temperature = (float) tmp * 0.25;

return MAX3185X_OK;
}

int Max3185x::readPacket31856()
Max3185xState Max3185x::readPacket31856()
{
uint8_t rx[7];
/* read Cold-Junction temperature MSB, LSB, Linearized TC temperature 3 bytes and Fault Status */
uint8_t tx[7] = {0x0a};
uint8_t rx[1 + 6];
/* read one dummy byte, Cold-Junction temperature MSB, LSB, Linearized TC temperature 3 bytes and Fault Status */
const uint8_t tx[1 + 6] = {0x0a};

int ret = spi_txrx(tx, rx, 7);
int ret = spi_txrx(tx, rx, sizeof(rx));

if (rx[6] & BIT(0)) {
livedata.state = MAX3185X_OPEN_CIRCUIT;
ret = -1;
if (ret) {
return MAX3185X_NO_REPLY;
} else if (rx[6] & BIT(0)) {
return MAX3185X_OPEN_CIRCUIT;
} else if (rx[6] & BIT(1)) {
livedata.state = MAX3185X_SHORT_TO_VCC;
ret = -1;
return MAX3185X_SHORT_TO_VCC;
}

if (ret) {
coldJunctionTemperature = NAN;
livedata.coldJunctionTemperature = 0;
temperature = NAN;
livedata.temperature = 0;
} else {
/* update livedata: float to int */
coldJunctionTemperature = (float)(rx[1] << 8 | rx[2]) / 256.0;
temperature = (float)((rx[3] << 11) | (rx[4] << 3) | (rx[5] >> 5)) / 128.0;
livedata.coldJunctionTemperature = coldJunctionTemperature;
livedata.temperature = temperature;
// Paranoid check.
bool allZero = true;
for (int i = 1; i < 6; i++) {
if (rx[i] != 0x00) {
allZero = false;
break;
}
}
if (allZero) {
return MAX3185X_NO_REPLY;
}

livedata.state = MAX3185X_OK;
if (1) {
// 10 bit before point and 7 bits after
int32_t tmp = (rx[3] << 11) | (rx[4] << 3) | (rx[5] >> 5);
/* extend sign: move top bit 18 to 31 */
tmp = tmp << 13;
tmp = tmp >> 13; /* shifting right signed is not a good idea */
temperature = ((float)tmp) / 128.0;
}
if (1) {
int16_t tmp = (rx[1] << 6) | (rx[2] >> 2);
/* extend sign */
tmp = tmp << 2;
tmp = tmp >> 2; /* shifting right signed is not a good idea */
coldJunctionTemperature = ((float)tmp) / 64.0;
}

return ret;
return MAX3185X_OK;
}

int Max3185x::readPacket()
Max3185xState Max3185x::readPacket()
{
int ret;

if (type == UNKNOWN_TYPE) {
ret = detect();
if (ret < 0) {
return ret;
type = detect();
if (type == UNKNOWN_TYPE) {
livedata.state = MAX3185X_NO_REPLY;
}
}

if (type == MAX31855_TYPE) {
return readPacket31855();
livedata.state = readPacket31855();
} else if (type == MAX31856_TYPE) {
return readPacket31856();
livedata.state = readPacket31856();
}

if (livedata.state == MAX3185X_OK) {
/* update livedata: float to int */
livedata.coldJunctionTemperature = coldJunctionTemperature;
livedata.temperature = temperature;
} else {
coldJunctionTemperature = NAN;
livedata.coldJunctionTemperature = 0;
temperature = NAN;
livedata.temperature = 0;
}

/* in case of communication problems - reinit */
if (livedata.state == MAX3185X_NO_REPLY) {
livedata.commErrors++;
type = UNKNOWN_TYPE;
}

return -1;
return MAX3185X_OK;
}

void Max3185xThread::ThreadTask() {
Expand Down
Loading