RF and Thermocouple Code Clashing

Hello all,

I am trying to use a ZetaRF 433MHz module along with a MAX31855K and ADG608 to read thermocouple data. The problem I’m having is that the code worked fine individually but when I combined it I have problems.

First the thermocouple code worked but the rf didn’t so I found alternative thermocouple code which doesn’t use any libraries but now the RF works and the thermocouple just outputs all zeros even for the internal temperature. This makes me think one is affecting the SPI signals of the other somehow but I don’t understand enough about it to figure out what. Any suggestions?

#include <Wire.h>
#include <GY80.h>
#include <ZetaRF.h>

GY80 sensor = GY80(); //create GY80 instance

// Zeta modules transmit messages using fixed size packets, define here the max size you want to use
#define ZETARF_PACKET_LENGTH 16

// Thermocouple Mux Pin
#define PINEN A3 // TC Mux Enable pins
#define PINA0 A0 // TC Mux Address 0 pin
#define PINA1 A1 // TC Mux Address 1 pin
#define PINA2 A2 // TC Mux Address 2 pin

// Thermocouple MAX31855K Pins
#define PINSO 12 //TC ADC Slave Out pin (MISO)
#define PINSC 13 //TC ADC Serial Clock (SCK)
#define PINCS 7  //TC ADC Chip 

#define SHORT -1001
#define OPEN -1000

volatile int tcTemp[9];    // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

ZetaRF zeta(10, 9, 8);  // Pins: SPI CS, Shutdown, IRQ

char data[ZETARF_PACKET_LENGTH] = "Hello World!";
bool transmitting = false;
int LED1_PIN = 4;
int LED2_PIN = 5;
int LED3_PIN = 2;
int LED4_PIN = 3;

int readSPI() {
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
  return v;
}

void tcTempSetup() {
  pinMode(PINEN, OUTPUT);
  pinMode(PINA0, OUTPUT);
  pinMode(PINA1, OUTPUT);
  pinMode(PINA2, OUTPUT);
  pinMode(PINSO, INPUT);
  pinMode(PINCS, OUTPUT);
  pinMode(PINSC, OUTPUT);

  digitalWrite(PINEN, HIGH);   // enable the mux all the time
  digitalWrite(PINSC, LOW);    // put clock in low
  digitalWrite(PINCS, LOW);    // stop conversion, start serial interface

  // Timer0's overflow is used for millis() - setup to interrupt
  // in the middle and call the "Compare A" function below
  OCR0A = 0x80;
  TIMSK0 |= _BV(OCIE0A);
}

void setup()
{
  Serial.begin(115200);
  tcTempSetup();
  delay(1000);
  
  Serial.println("Starting Zeta TxRx...");

    
    // initialize the LED pins as outputs.
    pinMode(LED1_PIN, OUTPUT);
    pinMode(LED2_PIN, OUTPUT);
    pinMode(LED3_PIN, OUTPUT);
    pinMode(LED4_PIN, OUTPUT);

  // Initialize Zeta module, specifing channel and packet size
  zeta.begin(2, ZETARF_PACKET_LENGTH);

  // Print some info about the chip
  /*const Si4455_PartInfo &pi = zeta.readPartInfo();
  Serial.println("----------");
  Serial.print("Chip rev: "); Serial.println(pi.CHIPREV);
  Serial.print("Part    : "); Serial.println(pi.PART.U16);
  Serial.print("PBuild  : "); Serial.println(pi.PBUILD);
  Serial.print("ID      : "); Serial.println(pi.ID.U16);
  Serial.print("Customer: "); Serial.println(pi.CUSTOMER);
  Serial.print("Rom ID  : "); Serial.println(pi.ROMID);
  Serial.print("Bond    : "); Serial.println(pi.BOND);
  Serial.print('\n');

  const Si4455_FuncInfo &fi = zeta.readFuncInfo();
  Serial.print("Rev Ext   : "); Serial.println(fi.REVEXT);
  Serial.print("Rev Branch: "); Serial.println(fi.REVBRANCH);
  Serial.print("Rev Int   : "); Serial.println(fi.REVINT);
  Serial.print("Patch     : "); Serial.println(fi.PATCH.U16);
  Serial.print("Func      : "); Serial.println(fi.FUNC);
  Serial.print("SVN Flags : "); Serial.println(fi.SVNFLAGS);
  Serial.print("SVN Rev   : "); Serial.println(fi.SVNREV.U32);
  Serial.println("----------");//*/
  
  // Set module in receive mode
  zeta.startListening();

    sensor.begin();       //initialize sensors

  Serial.println("Init done.");
}

// Interrupt is called every millisecond
SIGNAL(TIMER0_COMPA_vect) {
  static byte ms = 0;
  static byte ch = 0;

  if (ms == 0) {
    // select the thermocouple channel on the mux
    digitalWrite(PINA0, ch & 1);
    digitalWrite(PINA1, ch & 2);
    digitalWrite(PINA2, ch & 4);
    // ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
  } else if (ms == 5) {
    // begin conversion
    digitalWrite(PINCS, HIGH);
    // ... wait 100 mS for conversion to complete
  } else if (ms == 105) {
    // stop conversion, start serial interface
    digitalWrite(PINCS, LOW);
    // 100nS min. delay implied

    int rawTC = readSPI();
    int rawIT = readSPI();

    int tempC = rawTC / 4;
    if (rawTC & 1) {
      if (rawIT & 1) {
        tempC = OPEN;
      }
      if (rawIT & 6) {
        tempC = SHORT;
      }
    }
    tcTemp[ch] = tempC;

    if (++ch == 8) {
      tcTemp[8] = rawIT / 64; // internal temperature reduced to quarter degree C
      ch = 0;
    }
    ms = 255; // ++ will make this 0
  }
  ms++;
}

void loop()
{
  LED_TEST();

  GY80(); 

  MAX31855K();
    
  TRANSMIT();
}

void LED_TEST(){
  digitalWrite(LED1_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED1_PIN, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(LED2_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED2_PIN, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(LED3_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED3_PIN, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(LED4_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED4_PIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

void GY80(){
  GY80_scaled val = sensor.read_scaled();       //get values from all sensors
    // print out values

    Serial.print("Mag:");                         //magnetometer values
    Serial.print(val.m_x,2);
    Serial.print(',');
    Serial.print(val.m_y,2);
    Serial.print(',');
    Serial.print(val.m_z,2);
    Serial.print(' ');
    Serial.print("Acc:");                         //accelerometer values
    Serial.print(val.a_x,3);
    Serial.print(',');
    Serial.print(val.a_y,3);
    Serial.print(',');
    Serial.print(val.a_z,3);
    Serial.print(' ');
    Serial.print("Gyro:");                        //gyroscope values
    Serial.print(val.g_x,1);
    Serial.print(',');
    Serial.print(val.g_y,1);
    Serial.print(',');
    Serial.print(val.g_z,1);
    Serial.print(' ');
    Serial.print("P:");                           //pressure values
    Serial.print(val.p,5);
    Serial.print(' ');
    Serial.print("T:");                           //temperature values
    Serial.println(val.t,1);


    delay(250);        // delay in between reads for stability
}

void MAX31855K(){
 for(byte j = 0; j < 9; j++) {
    Serial.print((word)j);
    Serial.print('=');

    // access thermocouple readings with interrupts disabled to prevent 'shearing'
    noInterrupts();
    int t = tcTemp[j];
    interrupts();

    if (t == OPEN) {
      Serial.print("open");
    } else if (t == SHORT) {
      Serial.print("short");
    } else {
      Serial.print(t / 4);
    }
    Serial.print(' ');
  }
  Serial.println("");
  delay(1000);
}

void TRANSMIT(){
// Send any data received from serial
  

    Serial.print("Sending >");
    Serial.write(data, ZETARF_PACKET_LENGTH);
    Serial.print("<\n");

    // Send buffer
    transmitting = true;  // Only one at a time!
    zeta.sendPacket((const uint8_t*)data);  // Use channel set with begin()
    // Module will automatically return to listening mode
  

  // Check if message was transmitted successfully
  if (zeta.checkTransmitted()) {
    transmitting = false;
    Serial.println("msg transmitted");
  }//*/

  // Check incoming messages and print
  if (zeta.checkReceived()) {
    Serial.print("> ");
    zeta.readPacket((uint8_t*)data);
    Serial.write(data, ZETARF_PACKET_LENGTH);
    Serial.print('\n');
  }//*/
  
  delay(10);

}

I think the problem is the zeta library is using hardware SPI and then preventing the MAX31855 spi from working. I’ve tried to disable the zeta spi while the MAX spi code runs using the following code

int readSPI() {
 zeta.SPI_stop();
 delay(100);
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
 zeta.SPI_start();
  return v;
}

which is linked to the following in the library

void ZetaRF::SPI_start()
{
	clearCS();
	deassertShutdown();
	//SPI.beginTransaction();
}
void ZetaRF::SPI_stop()
{
	setCS();
	assertShutdown();
	//SPI.endTransaction();
}

void ZetaRF::assertShutdown() const
{
    digitalWrite(m_sdnPin, HIGH);
}
void ZetaRF::deassertShutdown() const
{
    digitalWrite(m_sdnPin, LOW);
}

void ZetaRF::clearCS() const
{
    digitalWrite(m_csPin, LOW);
    SPI.beginTransaction(ZETARF_SPI_SETTINGS);
}
void ZetaRF::setCS() const
{
    SPI.endTransaction();
    delayMicroseconds(1);
    digitalWrite(m_csPin, HIGH);
}

but I’m still not getting anything from the MAX31855. Am I completely wrong in thinking that code should have disabled the hardware SPI to allow another SPI to work?

Are both devices on the same SPI bus (i.e. do they share CLK, MOSI, MISO)?

Does each have its own chip select that you assert (and de-assert the other) before trying to access via SPI?

Yes they share the same bus, the pins are as follows

[u]MAX31855K[/u] SO -> MISO (D12) CS -> D7 SCK -> SCK (D13)

[u]ZetaRF[/u] SCLK -> SCK (D13) SDI -> MOSI (D11) SDO -> MISO (D12) nSEL -> D10 nIRQ ->D8 SDN -> D9

In the code from my first post, the interrupt for the MAX chip sets the chip select low to take a reading and then back to high. I'm not sure about the Zeta library, it is using the SPI library so I presume it handles it properly. I have tried putting digitalWrite(10, HIGH); in the interrupt routine to try to force the Zeta chip select pin to deselect but no luck.

Both chips work individually but not when the code is combined. I can only find one ZetaRF library but I've tried four different codes for the MAX31855K, all worked individually but don't when combined with the Zeta library.

In the zeta library I see the line

#define ZETARF_SPI_SETTINGS SPISettings(1000000UL, MSBFIRST, SPI_MODE0)

and

SPI.beginTransaction(ZETARF_SPI_SETTINGS);

Could this be causing the SPI to stop working for the other?

I'm really not sure if the SPI library handles the CS lines for your of if that needs to be done "manually".