Connected SPI device causing M0 to not boot [solved]

Started by mwolter, August 01, 2018, 12:10:32 PM

mwolter

Hello,
I am in the process of moving a project from a Moteino to a Moteino M0 and ran into an issue with an Adafruit MAX31855 thermocouple amplifier. If I have the MISO pin from the 31855 connected to the M0, it will not boot when power is applied. I have to remove the pin, then reconnect it after the M0 has booted. After it's booted, I reconnect the MISO port and the temperature is read properly and the M0 functions just fine. As far as I can tell, there doesn't appear to be anything wrong with my code and this worked fine on a Moteino previously.

Is there anything I should be doing differently with the M0?

Below is my code related to the 31855:

#include <Adafruit_MAX31855.h>	//get library from: https://github.com/adafruit/Adafruit-MAX31855-library tested using Sept 26, 2016 version

int oilTempCsPin = 2; // spi client select (CS) pin
unsigned long oilTempLastRead; // millis of the last read interval
int oilTempUpdateInterval = 300; // interval for temperature readings in ms
double oilTemp = 0; //most current temperature reading
int oilTempErrorCount = 0; //count of thermocouple read errors

Adafruit_MAX31855 oilTempObj(SCK, oilTempCsPin, MISO);

void loop() {

		if (millis() - oilTempLastRead > oilTempUpdateInterval) { // successive temp readings faster than 220ms will cause errors and the temp will remain constant

			double f = oilTempObj.readFarenheit();
			if (isnan(f)) { //was there a communication with the thermocouple
				oilTempErrorCount++;
				if (oilTempErrorCount >= 5) {
					oilTemp = -999;
					oilTarget = -999;
					SerialUSB.println("{\"Error\":\"Oil Temp Sensor Malfunction. Unplugged?\"}");
				}
			}
			else {
				oilTempErrorCount = 0; //reset error counters
				oilTemp = f;
			}

			oilTempLastRead += oilTempUpdateInterval;
		}
}

Felix

What exactly do you mean by not "boot"?
There is a bootloader which always runs when you plug it in. If there is a sketch it will jump at that location, otherwise it will stay in the bootloader. FWIW a double RESET-tap would also put it in bootloader.

Can you confirm that your M0 does not get into the SKETCH ?
By putting something like a BLINK pattern followed by a delay(), before running your sketch code?

mwolter

#2
A better explanation is that it does not run the sketch. Still learning the Moteino M0 :) The sketch does a serial print of the thermocouple value every four seconds, so this is my sketch run indicator.

With the MISO pin connected, I do not receive the serial print. Tried power cycling the MISO pin connected, tried pressing the reset button, M0 still does not run the sketch.

I have to physically remove the MISO pin, reset the M0, restart the serial monitor, wait for the error reports (because the pin is disconnected), then insert the MISO pin. When I do this procedure, everything works fine. Obviously, this is not ideal since a normal power outage will cause the sketch to not load.

Felix

I'm not sure how to try to reproduce this without the actual hardware and code you're using.
If you're up for sending your setup over I can give it a go. I know it's inconvenient but ... unless you have other suggestions I'm not sure how to help.
Do you have a logic analyzer? I would probe the SPI bus during boot and see what's going on there.

mwolter

Switched to a generic MAX6675 module using the code below and it works fine. Not sure what the issue was but I know this is good.

#include <SPI.h>

int oilTempCsPin = 2; // spi client select (CS) pin
unsigned long oilTempLastRead; // millis of the last read interval
int oilTempUpdateInterval = 300; // interval for temperature readings in ms
double oilTemp = 0; //most current temperature reading
int oilTempErrorCount = 0; //count of thermocouple read errors

float thermocoupleReadC(int _tcCsPin) {
	bool _tcFirst = true;
	float _tcTemps[6];

	unsigned int tcData;
	float tcTemp, tcAvgTemp;

	//read the temperature

	SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV16, MSBFIRST, SPI_MODE1));

	digitalWrite(_tcCsPin, LOW);
	tcData = SPI.transfer(0x00) << 8;
	tcData |= SPI.transfer(0x00);
	digitalWrite(_tcCsPin, HIGH);

	SPI.endTransaction();

	if (tcData & 0x0004) {                  //open thermocouple circuit
		return -1.0;
	}
	else {
		tcTemp = (tcData >> 3) / 4.0;         //calculate deg C
		if (_tcFirst) {                       //if first time through, fill the readings array
			_tcFirst = false;
			for (int i = 0; i<6; i++) {
				_tcTemps[i] = tcTemp;
			}
		}
		for (int i = 0; i<5; i++) {           //shift prior readings
			_tcTemps[i] = _tcTemps[i + 1];
		}
		_tcTemps[5] = tcTemp;                   //put the new reading in at the top end of the array
		tcAvgTemp = 0.0;                      //calculate the average
		for (int i = 0; i<6; i++) {
			tcAvgTemp += _tcTemps[i];
		}
		tcAvgTemp /= 6.0;
		return tcAvgTemp;
	}
}

float thermocoupleReadF(int _ssPin) {
	float tcTempC;

	tcTempC = thermocoupleReadC(_ssPin);
	if (tcTempC < 0.0) {
		return tcTempC;
	}
	else {
		return tcTempC * 9.0 / 5.0 + 32.0;
	}
}

void setup() {
	pinMode(MOSI, OUTPUT);
	pinMode(MISO, INPUT);
	pinMode(SCK, OUTPUT);
	SPI.begin();                            //initialize SPI

	pinMode(oilTempCsPin, OUTPUT);
	digitalWrite(oilTempCsPin, HIGH); //Start de-selected
}

void loop() {
		if (millis() - oilTempLastRead > oilTempUpdateInterval) { // successive temp readings faster than 220ms will cause errors and the temp will remain constant
			
			oilTemp = thermocoupleReadF(oilTempCsPin);
			oilTempLastRead += oilTempUpdateInterval;
		}
}

Felix

Ok .. interesting.
Is this considered solved then?

mwolter

Yessir, I'll just stick with this amp. Don't need negative temp readings, so this should be fine.