More questions SPI Manual Correctly Previous Post MAX31855, Screen Freezes why? CLK?

Status
Not open for further replies.

Bastiaan

Well-known member
Hi fellow engineers

good morning,

I am one step further, after a hint from the Maxim Integrated guys. The MAX31855 needs to be set to SPI_MODE 0.
The PDF_TOTAL is the total schematic how it is wired on the PCB.
The upper left corner shows the DCDC converter,
pins out pump
header to front panel with all the voltages 24,12,5,3.3V with leds, RGB Encoder with a push button which is connected with 4 10K resistors and 2x 10nF caps.
The upper right corner shows all 8 OPA365, voltage follower and amplification from 140mV to 3.3V all calculated and sometimes pulled up by a resistor are read out by the Internal ADC.
The lower right shows the 18V25, VNH5019 Hbridge drivers for 3x Peltier groups of each 16.7A.

here is the pdf schematic. Ino file, recording oscilloscope (CLK looks ackward),
View attachment Snippet from the Serial monitor with both Functions running after each other.txt secondrun.pngView attachment 2_2.pdf

so I have followed the manual as https://www.pjrc.com/better-spi-bus-design-in-3-steps/
  1. hooked up the CS Pins with a 4.7K resistor to VCC at the MAX31855
  2. hooked up the MISO line to a voltage divider 10K on the breadboard. Check: no action on the MISO it floats to 1.697V on the oscilloscope, so that’s good.
  3. Changed the SPI settings for the MAX31855 to SPI_MODE 0, with MSBFIRST, the values such as temperatures and words are displayed on the screen but no refresh of the screen.
  4. The CS Pins I am using are: 14,15,16,17 on the Teensy3.6 for the MAX31855
  5. I am getting getting read out at the serial monitor if both functions are uncommented, and also serial prints at the end of the TFT function that are shown in the Snippet.txt
  6. In total there are 4 functions in void loop():
  7. a InternalADC
  8. b MenuCheck()
  9. c MenuCountdown()
  10. d Thermocouple1_4()
  11. The TFT MenuCountdown() program runs parallel to the menuCheck() function. By rotating the knob of the encoder I can change the value , let’s say 0…100 and by clicking again I can go to menu2 3,4, and so on, this is put on the TFT Screen in the MenuCountDown()
  12. These values are then copied to the same TFT function ( setting the Setpoint of the PID control )//momentarily it is commented out.

  • For a Test I checked: void loop the program Thermocouple1_4(); has been commented out. I get data on the tft screen from the Currents (which is jibberish) because there is not current yet, and the Internal ADC is working in the teensy.

  • If both programs are run in the void loop I get: a diagnostics check from the Screen that everything is a OK.
  • The TC0,TC1 and so on are the Internal and External Temperatures from each of the Thermocouples. NOT is not calibrated the max31855 has to undergo a calibration if it goes below Zero.


TC0 pin14 INT 25.88 NOT 23.75

TC1 pin15 INT 26.50 NOT 25.75

TC2 pin16 INT 26.31 NOT 25.00

TC3 pin17 INT 25.38 NOT 24.25
:(


Total Code: if Thermocouples1_4(); is commented out I get the Data on the Screen. if not commented out all data is still visible on the Serial Monitor, screen freezes

I know this is childsplay, but I would like to understand why it isn’t working properly and solve it, i tried all my tricks up my sleeve, and I am desperately in need of help.

Code:
/* constants ================================================================ */
const int ledPin = LED_BUILTIN;
const int ssPin = 10;

#include <SPI.h>
#include "Adafruit_MAX31855.h"
#include "HX8357_t3n.h"
#include <FlickerFreePrint.h>// library to draw w/o flicker
#include <math.h>
#include <stdio.h>

#include <ButtonEvents.h>
#include <ADC.h>
#include <Encoder.h>
#include <PID_v1.h>
/* INPUTS and OUTPUTS
 * DIR= direction of the magnet, peltier (HOT COOL) =OUTPUTS
 * FLOWsensor = INPUT
 * PWM= Output TEC1,TEC2,EMAGNET,PUMP different speeds for pwm.
 * FLT= Faults from the Hbridge Drivers
 * CS=Currentsense from the 4 HBridge drivers
 */



const int DIRmagnetLeft=0;
const int DIRmagnetRight=33;
const int DIR_TEC_Cool=2;
const int DIR_TEC_HOT=3;

const int PWM_DRV_TEC1  = 4;
const int PWM_DRV_TEC2  =5;
const int PWM_PUMP      =6;
const int PWM_EMAGNET   =7;
const int PWM_FAN       =36;
const int FLOW_Sensor   =25;
const int FLT_Peltier1  =29;
const int FLT_Peltier2  =30;
const int FLT_PMP       =31;
const int FLT_EMAG      =32;

const int CSTEC1=A9;
const int CSTEC2=A8;
const int CSPUMP=A7;
const int CSEMAG=A6;

const byte buttonPin = 20;

//SPI defines
#define MAXCLK 13 //max31855 nothing else.
#define MAXDO   9
#define TFT_DC  10
#define TFT_CS 8
#define TFT_RST -1


//TFT size
#define TS_MINX 3800
#define TS_MAXX 100
#define TS_MINY 100
#define TS_MAXY 3750

//TFT defined colors
#define C_BLACK      0x0000
#define C_BLUE        0x001F
#define C_RED         0xF800
#define C_GREEN       0x07E0
#define C_CYAN        0x07FF
#define C_MAGENTA     0xF81F
#define C_YELLOW      0xFFE0
#define C_WHITE       0xFFFF

//constructors for TFT without flickering
HX8357_t3n tft = HX8357_t3n(TFT_CS, TFT_DC, TFT_RST);
FlickerFreePrint<HX8357_t3n> Data1(&tft, C_WHITE, C_BLACK);
FlickerFreePrint<HX8357_t3n> Data2(&tft, C_WHITE, C_BLACK);


SPISettings settingsTFT(26000000, MSBFIRST, SPI_MODE3);
SPISettings SettingsA(5000000,MSBFIRST,SPI_MODE0);


unsigned long endmicros;  //speed check variables
unsigned long currentmicros;

//menu Check values to check consistency of the menu loop.

byte menuCount = 1;

byte IntCount= 1;
byte dir = 0;
bool runState = false;
bool runState2 = false;
unsigned int count = 0;            // how many times has it changed to low
unsigned long countAt = 0;         // when count changed
unsigned int countPrinted = 0; 
unsigned int icount = 0;            // how many times has it changed to low
unsigned long icountAt = 0;         // when count changed
unsigned int icountPrinted = 0;

long oldPosition  = -100;
long newPosition;
long Position;

long oldPWMPosition=-100;
long PWMPosition=1;


//---------- values for the ad7124
const double Gain = 16;
const double Rf = 5.11E3;
const long Zero = 1L << 23;
const long FullScale = 1L << 24;

//variables returned from analog inputs
int CSRAWTEC1_value;
int CSRAWTEC2_value;
int CSRAWPUMP_value;
int CSRAWEMAG_value;

float Currentfactor1=5.06;
float Currentfactor2=5.06;
float Currentfactor3=5.06;
float Currentfactor4=5.06;

float TEC1Current;
float TEC2Current;
float PumpCurrent;
float EMAGCurrent;

int PMPSpeed_screen;
int EMAGNET_Screen;

long SBraw[7];
double SBvolt[7];
long dataWord;
byte statusWord;
byte ch;
/* constants ================================================================ */
int filterWord = 100;

// Sample Speed Setting (Full Power Sinc3 Filter Mode)
//  FW  |  SPS  |  SPS/Ch
//  600 |    6  |     1
//  100 |   60  |    10
//   40 |  156  |    26
//   20 |  300  |    50

float j;
unsigned long StartTime, EndTime;
char str[30];

Adafruit_MAX31855 TH1(MAXCLK, 14, MAXDO);
Adafruit_MAX31855 TH2(MAXCLK, 15, MAXDO);
Adafruit_MAX31855 TH3(MAXCLK, 16, MAXDO);
Adafruit_MAX31855 TH4(MAXCLK, 17, MAXDO);

Adafruit_MAX31855 *all_sensors[] ={&TH1,&TH2,&TH3,&TH4};




//encoder Values
float TempValue=0;
int PMPSpeed=0;
int EMAGNET=0;
int SampleTime=1000;  // 1 second
int Repitition_rate=1;
unsigned int Duration_ms_ON=1000; // 1 second default
unsigned int Duration_ms_OFF=1000;//default
unsigned long Time_NOW = 0;
int ON_LT3760=LOW;
int minimumLT3760=10; //minimum span needed to switch on off the lt3760
unsigned int ON_Time1=1000; // preliminary values at start up
unsigned int OFFTime1=5000;
unsigned long previousMillis=0;
unsigned long DISPLAY_REFRESH1=1000;
unsigned long Interval=1000;
unsigned long nowMillis;//important
elapsedMillis ElapsedOFF;
elapsedMillis ElapsedON;
int repeats=1;
int Intensity=0;
int i=0;


//default Configuration Current Direction Bipolar to Unipolar
boolean Bipolar=true;
boolean Unipolar=false;
int ConfigMin=2048;
int ConfigMax=4095;
int EmagnetConfig;

double c[4];
double c1[4];
double intern[4] ;



//using namespace Ad7124;
//Ad7124Chip adc;

//debounce code//
ButtonEvents myButton;  // Instantiate a Bounce object
Encoder enc(27,28); //instance Encoder Rotary
ADC *IADC = new ADC(); //class ADC from the teensy read in Currents


uint8_t Stat, TFT_Stat;


//PID Parameters
double Setpoint, Input, Output;
double aggKp=4, aggKi=0.2, aggKd=1;
double consKp=1, consKi=0.05, consKd=0.25;

PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);

long mmap0(long x, long mn1,long mx1, long mn2, long mx2)
{
  return mn2+(x-mn1)*(mx2-mn2)/(mx1-mn1);
}
long mmap1(long x, long mn1,long mx1, long mn2, long mx2)
{
  return mn2+(x-mn1)*(mx2-mn2+1)/(mx1-mn1+1);
}

int InternalADC()
{
  IADC->adc0->startContinuous(CSTEC1);
  IADC->adc0->startContinuous(CSTEC2);
  IADC->adc0->startContinuous(CSPUMP);
  IADC->adc0->startContinuous(CSEMAG);
  CSRAWTEC1_value = IADC->adc0->analogRead(CSTEC1);
  CSRAWTEC2_value = IADC->adc0->analogRead(CSTEC2);
  CSRAWPUMP_value = IADC->adc0->analogRead(CSPUMP);
  CSRAWEMAG_value =IADC->adc0->analogRead(CSEMAG);

    TEC1Current=CSRAWTEC1_value*Currentfactor1;
    TEC2Current=CSRAWTEC1_value*Currentfactor2;
    PumpCurrent=CSRAWPUMP_value*Currentfactor3;
    EMAGCurrent=CSRAWEMAG_value*Currentfactor4;

  
  
}


void setup() 
{

  pinMode(buttonPin,INPUT);
  pinMode(FLT_Peltier1,INPUT);
  pinMode(FLT_Peltier2,INPUT);
  pinMode(FLT_PMP,INPUT);
  pinMode(FLT_EMAG,INPUT);
  pinMode(CSTEC1,INPUT);
  pinMode(CSTEC2,INPUT);
  pinMode(CSPUMP,INPUT);
  pinMode(CSEMAG,INPUT);
  
  
  pinMode(DIRmagnetLeft,OUTPUT);
  pinMode(DIRmagnetRight,OUTPUT);
  pinMode(DIR_TEC_Cool,OUTPUT);
  pinMode(PWM_DRV_TEC1,OUTPUT);
  pinMode(PWM_DRV_TEC2,OUTPUT);
  pinMode(PWM_PUMP,OUTPUT);
  pinMode(PWM_EMAGNET,OUTPUT);

  //SPI
//  pinMode(AD7124_CS, OUTPUT);
 
  pinMode(14,OUTPUT);
  pinMode(15,OUTPUT);
  pinMode(16,OUTPUT);
  pinMode(17,OUTPUT);
  
  pinMode(TFT_CS, OUTPUT);

  myPID.SetMode(AUTOMATIC);
  myPID.SetSampleTime(SampleTime);
  analogWriteResolution(12);
  analogWriteFrequency(PWM_DRV_TEC1,25000);
  analogWriteFrequency(PWM_DRV_TEC2,25000);
  analogWriteFrequency(PWM_PUMP,200);
  analogWriteFrequency(PWM_EMAGNET,10000);

IADC->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
IADC->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // change the sampling speed
IADC->adc0->setAveraging(4);  
IADC->adc0->setResolution(12);
IADC->startSynchronizedContinuous(CSTEC1,ADC_0);
IADC->startSynchronizedContinuous(CSTEC2,ADC_0);
IADC->startSynchronizedContinuous(CSPUMP,ADC_0);
IADC->startSynchronizedContinuous(CSEMAG,ADC_0);

myButton.attach(buttonPin);
myButton.activeHigh();
myButton.debounceTime(5); //apply 15ms debounce
myButton.doubleTapTime(250);//apply 250ms Double click detection

 
  SPI.begin();
     //Initialize serial and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
  {
    ;
  }

      for(int i=0;i>4;i++)
        {
        SPI.beginTransaction(SettingsA);
        digitalWrite(i+14,LOW);
        
        if (all_sensors[i]->begin()) 
        {
          Serial.println("ERROR.");
          while (1) delay(10);
        }
        Serial.println("DONE.");
       digitalWrite(i+14,HIGH);
       
        SPI.endTransaction();
        } 
      
  SPI.beginTransaction(settingsTFT);
  digitalWrite(TFT_CS,LOW);
  tft.begin();

  uint8_t x = tft.readcommand8(HX8357_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(HX8357_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(HX8357_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(HX8357_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(HX8357_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  
  tft.setRotation(1);
  tft.fillScreen(C_BLACK);

  tft.fillRect(0, 30, 480, 10, C_RED);
  tft.fillRect(0, 140, 480, 10, C_BLUE);
  digitalWrite(TFT_CS,HIGH);
  SPI.endTransaction();

   
 
  }




void loop() 
{
 nowMillis=millis();
 InternalADC(); 
 Menu1Check();
 
      
       
  
      Menu1Countdown(); 
   
     
      Thermocouples1_4();
//    
     
      
  }        
       

 

    //save value
    
 
 





int Menu1Check() 
{
if (myButton.update()==true) 
  {
   
  
  switch(myButton.event()) 
  {



    
      
      // things to do if the button was tapped (single tap)
      case (tap) : 
      {
        Serial.print("Single Click event detected = ");   
       
         menuCount=menuCount+1;
         
      
        
        Serial.print("MenuCountUp = ");   
        Serial.println(menuCount);
               
        break;
      }
  
  case (doubleTap) : 
      {
        Serial.print(" DOUBLE-TAP event detected ");
    

        menuCount=menuCount-1;
        Serial.print(" DB TAP Count Down ");
        Serial.println(menuCount);
        break;
      } 
   
   
   
   
   
   
   
  }
 
      
    }
  if (menuCount>8) 
  {
    Serial.print("menu larger as 8");
    menuCount = 1;
  }

if (menuCount == 1) 
  { 
    Serial.println("MENU1 set SampleTime ");

      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
//      newPosition=newPosition/4;
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>0&&newPosition<100)
    {
    SampleTime = newPosition;
    Serial.print(" SampleTime in ms ");
    Serial.print(SampleTime);

    }
 }
   
  

  if (menuCount == 2) 
  { 
    Serial.println("MENU2 set Temperature");

      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
     newPosition=newPosition/4;
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>-10&&newPosition<60)
    {
    TempValue = constrain(newPosition,-10,60);
    Serial.print(" Temperature ");
    Serial.print(TempValue);

    //input=value from the thermocouple sensor
    
    Setpoint=TempValue;
    

    }
  }//menuCount2
    
   
    // use menuCount2 for setting 10/100th degree , add both values together after menucount2.


   

   if (menuCount == 3) 
  {
    Serial.println("MENU3 set Pump Speed");  
    /*signal is amplified with an extra circuit under the board with a OPA365, Inverted
     *  3.3V to 5V the pump requires 5V pwm at 25KHz green wire.
     * OPA365 8 SOIC pins 1,2,3,4. onesided dual Opamp.OPA2365. 
     * 6.9K and 3.7K are connected to the - pin. and 10K over the opamp.
     *                -- 10K-----
     * 3.3V --6.9K --|  -        | output
     *               |          -------------------
     *        |--3.7K      
     * 5V--- 3.9K----   +
     *              |
     *              |
     *              1K
     *              |
     *              -
     */

    
      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
    
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
      
     }
      if(newPosition>0&&newPosition<100)
    {
     Serial.print(newPosition);
     PMPSpeed=constrain(newPosition,0,100);
     newPosition=map(newPosition,0,100,0,4095);
    }
    
  }//menuCount3
  
   if(menuCount==4)
   {

     Serial.print("MENU4 set Bipolar or Unipolar");
    if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
      
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>=0&&newPosition<3)
    {
      Repitition_rate = newPosition;
    if(newPosition==0)
    {
      Serial.println("Bipolar selected");
      Bipolar=true;
     
    
     
    }
    if(newPosition==1);
    {
      Serial.println("Unipolar selected");
    }
      Bipolar=false;
      
 
     
    }
   }
      
   
   if (menuCount == 5) 
  {
    Serial.print("MENU5 set Emagnet Current");
       if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
      
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>0&&newPosition<100)
    {

      
      EMAGNET=constrain(newPosition,0,100);
      EmagnetConfig=map(newPosition,0,100,ConfigMin,ConfigMax);
      EMAGNET=map(EMAGNET,0,100,0,17);
      
//      digitalWrite(DIRmagnetLeft,HIGH);
//      digitalWrite(DirmagnetRight,LOW);
    }
    else
    {
      analogWrite(4, 0);
   
    }
  
}
 
   if (menuCount == 6) 
  {
    Serial.print("MENU6 set On time Duration");
      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
      newPosition=newPosition/4;
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>0&&newPosition<100)
    {
      Duration_ms_ON = newPosition*1000;
    Serial.print(" Duration_ms On ");
    Serial.println(Duration_ms_ON);

      //input=value from the thermocouple sensor

     
     
    }
       //out of boundary set to zero.
   }

      if (menuCount == 7) 
  {
    Serial.print("MENU6 set Off Time Duration");
      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
      newPosition=newPosition/4;
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>0&&newPosition<100)
    {
      Duration_ms_OFF = newPosition*1000;
    Serial.print(" Duration_ms Off= ");
    Serial.println(Duration_ms_OFF/1000);

      //input=value from the thermocouple sensor


    }
       //out of boundary set to zero.
   }
   
      if (menuCount == 8) 
  {
    Serial.print("MENU8 Repitition in Hz");
      if(oldPosition>=0&&oldPosition<100)
      oldPosition=0;   
      
      long newPosition = enc.read();
      
     if (newPosition != oldPosition) 
     {  
        oldPosition = newPosition;
        
        Serial.print(newPosition);
     }
   
    if(newPosition>0&&newPosition<25)
    {
      Repitition_rate = newPosition;
    Serial.print(" Repitition_Rate in Hz ");
    Serial.println(Repitition_rate);

     


    }
       //out of boundary set to zero.
   }

}


int Thermocouples1_4() //see instanciation pointer to array class TH1,TH2,TH3,TH4
{
/*
 * five steps to calulate from a linear voltage to temperature to non linear max31855 which truely resembles the Temperature in 5 Steps
 * 1 substract the min temperature - internal temperature.
 * 
 * 2 multiply min temperature x this Thermocouple K voltage (check max31855 datasheet on ThermocoupleK voltage which is 0.041276mV/C)
 * 3 Calculate Cold Junction equivalent thermocouple voltage using the formula below with NIST
 *   𝑚𝑉=𝐴0+𝐴1∗𝑇𝑒𝑚𝑝+𝐴2∗𝑇𝑒𝑚𝑝'^'2+𝐴3∗𝑇𝑒𝑚𝑝'^'3+⋯+𝐶0∗𝑒𝐶1∗(𝑇𝑒𝑚𝑝−𝐶2)'^'2
 * 4 add cold junction equiv calculated in step 3.  
 * 5 use the result of step 4 and the NIST voltage to tempeature (inverse) coefficients B0,B1,B2 to calculate the cold junction compensation, lineariszed value
 * 𝑇𝑒𝑚𝑝=𝐵0+𝐵1∗𝑚𝑉+𝐵2∗𝑚𝑉2+𝐵3∗𝑚𝑉3+⋯
 * 0+(2.52∗101∗−3.528157)+(−1.17∗−3.5281572)+(−1.08∗−3.5281573)+⋯=−99.16
 */

   
   
   

     for(int i=0;i<4;i++)
     {
     SPI.beginTransaction(SettingsA);
     digitalWrite(14+i,LOW);
     Serial.print("TC");
     Serial.print(i);
     Serial.print(" pin");
     Serial.print(14+i);
     Serial.print(" INT ");
     Serial.print(all_sensors[i]->readInternal());
     Serial.print(" NOT ");
     Serial.println(all_sensors[i]->readCelsius());
     if(all_sensors[i]->readCelsius()<0)//if temperature is lower than 0   ////Thermocouple 1
     {
     intern[i]=all_sensors[i]->readInternal();
     c1[i] = all_sensors[i]->readCelsius();
     double SubC1_int=c1-intern;
     double SubCalc=SubC1_int*0.041276; /*mV*/
     double E1=(-0.176*pow(10,-1));
     double E2=(0.389*pow(10,-1)*pow(intern[i],1));
     double E3=(0.186*pow(10,-4)*pow(intern[i],2));
     double E4=(-0.995*pow(10,-7)*pow(intern[i],3));
     double E5=(0.318*pow(10,-9)*pow(intern[i],4));
     double E6=(-0.561*pow(10,-12)*pow(intern[i],5));
     double E7=(0.561*pow(10,-15)*pow(intern[i],6));
     double E8=(-0.320*pow(10,-18)*pow(intern[i],7));
     double E9=(0.972*pow(10,-22)*pow(intern[i],8));
     double E10=(-0.121*pow(10,-25)*pow(intern[i],9));
     double E11=(0.119*pow(exp(-0.118*pow(10,-3)*(intern[i]-0.127*pow(10,3))),2));
     double E1_11=E1+E2+E3+E4+E5+E6+E7+E8+E9+E10+E11;
     double AddCJError=E1_11+SubCalc;
     double R1=0+(2.51734*pow(AddCJError,1));
     double R2=(-1.17*pow(AddCJError,2));
     double R3=(-1.08*pow(AddCJError,3));
     double R4=(-8.977*pow(10,-1)*pow(AddCJError,4));
     double R5=(-3.73*10*pow(10,-1)*pow(AddCJError,5));
     double R6=(-8.6632*pow(10,-2)*pow(AddCJError,6));
     double R7=(-1.045*pow(10,-2)*pow(AddCJError,7));
     double R8=(-5.1920577*pow(10,-4)*pow(AddCJError,8));
     double R9=0*pow(AddCJError,9);
     double R1_9=R1+R2+R3+R4+R5+R6+R7+R8+R9;
     Serial.print("Cold ");
     Serial.print("Corr Value ");
     Serial.println(R1_9/100000000);
     
     if (isnan(c1[i])) {
       Serial.print("Something wrong with Thermocouple ");
  
     } 
     else {
       Serial.print("C = ");
       Serial.println(c1[i]);
     }
     }
     else //this is the 0...500°
     {
     
     intern[i]=all_sensors[i]->readInternal();
     c[i]= all_sensors[i]->readCelsius();
  //   double SubC1_int=c1-intern;
  //   double SubCalc=SubC1_int*0.041276; /*mV*/
  //   double H1=(-0.17600413686*pow(10,-1));
  //   double H2=(0.389212049750*pow(intern,1));
  //   double H3=(0.185587700320*pow(10,-4)*pow(intern,2));
  //   double H4=(-0.99457592874*pow(10,-7)*pow(intern,3));
  //   double H5=(0.318409457190*pow(10,-9)*pow(intern,4));
  //   double H6=(-0.56072844889*pow(10,-12)*pow(intern,5));
  //   double H7=(0.560750590590*pow(10,-15)*pow(intern,6));
  //   double H8=(-0.320200720003*pow(10,-18)*pow(intern,7));
  //   double H9=(0.971511471520*pow(10,-22)*pow(intern,8));
  //   double H10=(-0.121047212750*pow(10,-25)*pow(intern,9));
  //   double H11=(0.1185976*pow(exp(-0.118343200*pow(10,-3)*(intern-0.126986*pow(10,3))),2));
  //   double H1_11=H1+H2+H3+H4+H5*H6+H7+H8+H9+H10+H11;
  //   double AddCJError=H1_11+SubCalc;
  ////   double E1=(-1.318058*pow(10,2)*pow(AddCJError,0));//inverse coefficients probably not the right one.
  ////   double E2=(4.830222*pow(10,1)*pow(AddCJError,1));
  ////   double E3=(-1.64603*pow(10,0)*pow(AddCJError,2));
  ////   double E4=(5.46473*pow(10,-2)*pow(AddCJError,3));
  ////   double E5=(-9.65071*pow(10,-4)*pow(AddCJError,4));
  ////   double E6=(8.802193*10*pow(10,-6)*pow(AddCJError,5));
  ////   double E7=(-3.11081*pow(10,-8)*pow(AddCJError,6));
  ////   double E8=(0*pow(10,0)*pow(AddCJError,7));
  ////   double E9=(0*pow(10,0)*pow(AddCJError,8));
  ////   double E10=(0*pow(10,0)+pow(AddCJError,9));
  //
  //   double E1=1;
  //   double E2=(2.508355*pow(10,1)*pow(AddCJError,1));
  //   double E3=(7.86010*pow(10,-2)*pow(AddCJError,2));
  //   double E4=(-2.50313*pow(10,-1)*pow(AddCJError,3));
  //   double E5=(-8.3152702*pow(10,-2)*pow(AddCJError,4));
  //   double E6=(-1.228034*10*pow(10,-2)*pow(AddCJError,5));
  //   double E7=(-9.804036*pow(10,-4)*pow(AddCJError,6));
  //   double E8=(-4.413030*pow(10,-5)*pow(AddCJError,7));
  //   double E9=(1.057734*pow(10,-6)*pow(AddCJError,8));
  //   double E10=(-1.052755*pow(10,-8)+pow(AddCJError,9));
  //   double E1_9=E1+E2+E3+E4+E5+E6+E7+E8+E9+E10;
  //   double CorVal=(E1_9/100000000);
  // 
  //   Serial.print(" Sensor ");
  //   Serial.print(i);
  //   Serial.print(" Real Temp ");
  //   Serial.println(CorVal);
                                    
     //Serial.print("F = ");
     //Serial.println(TH1.readFahrenheit());
     digitalWrite(14+i,HIGH);
     SPI.endTransaction();//----------------------------------------------------------------------------------
     
      }

    }//for

  }//millis
//thermocuple function 



int Menu1Countdown() //Menu 1 //Display
{
// get some data
     j += 0.0013;
   currentmicros = micros();
    long value;
  double voltage;

        Serial.print("test TC0");
        Serial.println(c[0]);
         Serial.print("test TC1");
        Serial.println(c[1]);
         Serial.print("test TC2");
        Serial.println(c[2]);
         Serial.print("test TC3");
        Serial.println(c[3]);

      
 /* all graphics commands have to appear within the loop body. */    
       SPI.beginTransaction(settingsTFT);
     
       digitalWrite(TFT_CS,LOW);
      
      Data1.setTextColor(C_WHITE, C_BLACK);
   
      tft.setTextSize(2);
      tft.setCursor(0, 0);
      tft.print("Emagnet program");
      

      Data1.print(j,2);
    //  // now let's see the tft update with FlickerFree
      tft.setTextSize(1);
      tft.setCursor(0,20);
      Data1.setTextColor(C_WHITE, C_BLACK);
      tft.print("Temperature readout");
      tft.print(" Voltages from Thermocouples ");
      tft.setTextSize(2);
      Data1.setTextColor(C_WHITE, C_BLACK);
      tft.setCursor(20,45);
      Data1.print(j,2);
      sprintf(str,"TempEmag: %lu",c[0]);
      Data1.print(str);
      tft.setCursor(20,60);
      Data1.print(c[0]); //C is a global variable!

      Data1.print(j,2);
      tft.setCursor(20,75);
      sprintf(str,"TempWater: %lu",c[1]);
      Data1.print(str);
     
      Data1.print(j,2);
      tft.setCursor(20,90);
      sprintf(str,"TempTEC2: %lu",c[2]);
      Data1.print(str);
      
      Data1.print(j,2);
      tft.setCursor(20,105);
      sprintf(str,"Temp: %lu",c[3]);
      Data1.print(str);
    
      tft.print(c[3]);
      tft.print(" C");
      tft.setCursor(20,120);
      tft.setTextSize(2);
      tft.setCursor(250,45);
      tft.print("Currents");
      tft.setTextSize(2);
      tft.setCursor(250,60);
      Data1.print(TEC1Current);
      tft.print("A");
      tft.setCursor(250,75);
      Data1.print(TEC2Current);
     tft.print("A");
     tft.setCursor(250,90);
      Data1.print(PumpCurrent);
      tft.print("A");
      tft.setCursor(250,105);
      Data1.print(EMAGCurrent);
      tft.print("A");
  

    
if(menuCount>0&&menuCount==1)
{ Serial.println("Starting MENU1");
  //Sample Time
  tft.setTextColor(C_WHITE, C_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10,130);
  tft.print("Variables to SET");
  tft.setTextSize(1);
  tft.setCursor(10,150);
  tft.print(" Setting Variables by rotating enc and press button to save");
  tft.setCursor(10, 170);
  tft.print("1* Samples/sec ");
  tft.print(SampleTime);
  
   
}
    

  if (menuCount > 1 && menuCount == 2) 
   {  Serial.println("Starting MENU2");
    //change PWMTEC2 Value on screen
    tft.setTextColor(C_WHITE, C_BLACK);
       tft.setTextSize(1);
   tft.setCursor(10,190);

   tft.print("2* Temp Setpoint= ");
   tft.print(TempValue);
    //Data1.print(SBvolt[0]);
  
   Input=0;//readin the temperature value from the sensor AD7124
      //out of boundary set to zero.
       double gap = abs(Setpoint-Input); //distance away from setpoint
  if (gap < 10)
  {  //we're close to setpoint, use conservative tuning parameters
    myPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
     //we're far from setpoint, use aggressive tuning parameters
     myPID.SetTunings(aggKp, aggKi, aggKd);
  }

   myPID.Compute();
      
   }
     
   if (menuCount > 2 && menuCount == 3) 
   { Serial.println("Starting MENU3");
    //set pump speed on the screen in PWM in 100%
    tft.setTextColor(C_WHITE, C_BLACK);
   tft.setTextSize(1);
   tft.setCursor(10,210);
   
   tft.print("3* PMPSPD_100% = ");
   tft.print(PMPSpeed);
            
   }

   if(menuCount>3 &&menuCount==4)  
   {     Serial.println("Starting MENU4");
    //Emagnet current
    tft.setTextColor(C_WHITE, C_BLACK);
        tft.setTextSize(1);
        tft.setCursor(10,230);
        tft.print("4* Set HALF or FULL Square Waveform  ");
        if(Bipolar==true)
        {
          tft.print(" Bipolar");
        }
        else
        {
          tft.print("Unipolar");
        }
        
   }
    
 if(menuCount>4 &&menuCount==5)  
   {
   Serial.println("Starting MENU5");
         //select Bipolar or Unipolar
        tft.setTextColor(C_WHITE, C_BLACK);
        tft.setTextSize(1);
        tft.setCursor(10,250);
        tft.print("5* Current Emagnet  ");
        tft.print(EMAGNET);
   }
     
      if(menuCount>5 &&menuCount==6)  
   {Serial.println("Starting MENU6");
    //set on Duration ms for the Emagnet
    tft.setTextColor(C_WHITE, C_BLACK);
        tft.setCursor(10, 270);
        tft.setTextSize(1);
        tft.print("5* OFFTime in ms ");
        tft.print(Duration_ms_ON);
 
   }

        if(menuCount>6 &&menuCount==7)  
   { Serial.println("Starting MENU7");
         analogWrite(PWM_DRV_TEC1, Output);
         analogWrite(PWM_DRV_TEC2, Output); 
    //set off Duration ms for the Emagnet
    tft.setTextColor(C_WHITE, C_BLACK);
        tft.setCursor(10, 290);
        tft.setTextSize(1);
        tft.print("6* ON_Time1 in ms ");
        tft.print(Duration_ms_OFF);

   }
    
   if(menuCount>7&&menuCount==8)
  { Serial.println("Starting MENU8");
    tft.setTextColor(C_WHITE, C_BLACK);
    tft.setCursor(10,310);
    tft.setTextSize(1);
    tft.print("7* Rep-Rate in Hz ");
    tft.print(Repitition_rate);   
     for(int i=0;i<Repitition_rate;i++)
     {
    if(ElapsedOFF>=Duration_ms_OFF) //OFFTime first
  {       
          
          
          if(Bipolar==false)
          {
          
          tft.fillRect(100,200,10, 10, C_RED);
   
          //ON_LT3760=LOW;
          // ElapsedOFF=ElapsedOFF-OFFTime1;
         
            
          ElapsedOFF=0; ElapsedON=0;
          analogWrite(4, 0);
          digitalWrite(2,LOW);//DIREMAGNETLEFT;
          }
  else if(ElapsedON>=Duration_ms_ON)//ONTime Second
        {  

    //add repetition rate Bipolar and Unipolar are taken into the timing.
          
        
          if(Bipolar==true)
          {
        
              tft.fillRect(100,200,10, 10, C_GREEN);
          //ON_LT3760=HIGH;
    //    delay(ON_Time1+minimumLT3760);
          digitalWrite(2,HIGH);//DIREMAGNETLEFT;
          analogWrite(4, EmagnetConfig);
          digitalWrite(33,HIGH);//DIREMAGNETRIGHT;

        
         
        }
        else
        {
          analogWrite(4, EmagnetConfig);
          digitalWrite(2,HIGH);//DIREMAGNETLEFT;
          digitalWrite(33,LOW);//DIREMAGNETRIGHT switched off.
        }
     }
  }
 }
}
 if(menuCount>8&&menuCount==9) 
 {Serial.println("Starting MENU9");
    tft.setTextColor(C_WHITE, C_BLACK);
    tft.setCursor(120,290);
    tft.setTextSize(1);
    tft.print(" ");
   }
   
if(menuCount>9&&menuCount==10)
{
  Serial.println("Starting Last MENU");
  menuCount=1; 
}
  
   tft.setTextColor(C_WHITE, C_BLACK);
   tft.setTextSize(2);
   tft.setCursor(0, 300);
   tft.print("M");
   tft.print(menuCount);

  
      
    
    
    
      
      
     
      // set PWM and Temperature
    //  Data1.setTextColor(C_WHITE, C_BLACK);
    //  tft.setTextSize(2);
    //  tft.setCursor(240, 45);
    //  tft.print(" Set Setpoint TEMP EMAG");
    //  tft.setCursor(240, 60);
    //  tft.print(" Temp Setpoint TEC2 100%");
    //  tft.setCursor(240, 75);
    //  tft.print(" PWM PMP  100%");
    
    
      
      
      
      // you must call the text colors for the object
    //  
    //  StartTime = millis();
    //
    //  // one call and flicker free paint is done
    //  tft.setCursor(300, 200);
    //  tft.setTextSize(2);
    //  Data1.print(j, 2);//for digits behidn teh comma
    //
    //  // lets see how fast
    //  EndTime = millis() - StartTime;
    //  sprintf(str, "=%lu", EndTime);
    //  Data1.print(str);
      
     digitalWrite(TFT_CS,HIGH);
       SPI.endTransaction();
     

   
 
}
 
Sorry, I have not gone through all of the flicker free code or the like, to know if for example they ever do anything like updateScreenAync or the like. That is the only case that the HX... library should still be active on SPI outside of call to tft.xxx

In your code you should never need to touch the CS pin (other than maybe before you init the display) nor ever need to do SPI.beginTransaction()... This is done internal to all graphic primitives...

Note: in your init code, I see where you set a lot of pins to OUTPUT or INPUT, but not sure if you set all of the CS pins HIGH before you initialized each device. If they are low, they will see the init code of other devices, which could confuse them.
 
So technically the graphic primitives, only require a pull up from CS to VCC and that’s it.
No digitalwrite of the CS pins, whatsoever. I’ll remove it and see what happens.

I’ll leave to it that The Max31855 still requires digitalWrite I think.

Thanks for the advice!

Check it first thing in the morning

Best regards

Bastiaan
 
What I did was test the two programs Separately in the void loop by commenting the first one out and the other in, and visa versa.

If this turns out not to be the problem, where do I look next?
Do I have to tinker with the Cpp files? Or HX8357 t3n?

Is it possible to write something as simple as this in the void loop?

Code:
If(digitalRead(TC_CSpin, HIGH))
{
Tft_Program();
}
Else
{
Thermocouple1_4();
}

This will probably only work for one MAX31855, not four because of the pins 17,16,15,14 and will trigger falsely.
If I have multiple devices of the same type in a function how do I check the function() if it has been run and the compiler is at the end of the Function()

Is it possible to check if a device is done, with something like SPI.Transfer(255)?
And check on the MISO line? Do I require digitalRead for this?

Sorry probably very confusing all of this, but those ideas came up during the day.

Why do ICs like MAX31855 require digitalWrite(TC_CSpin,LOW); as described in:

Many thanks!
 
Sorry I have not had a chance to look more at your code.

But Will try to answer some: Your setup code starts off like:
Code:
void setup() 
{

  pinMode(buttonPin,INPUT);
  pinMode(FLT_Peltier1,INPUT);
  pinMode(FLT_Peltier2,INPUT);
  pinMode(FLT_PMP,INPUT);
  pinMode(FLT_EMAG,INPUT);
  pinMode(CSTEC1,INPUT);
  pinMode(CSTEC2,INPUT);
  pinMode(CSPUMP,INPUT);
  pinMode(CSEMAG,INPUT);
  
  
  pinMode(DIRmagnetLeft,OUTPUT);
  pinMode(DIRmagnetRight,OUTPUT);
  pinMode(DIR_TEC_Cool,OUTPUT);
  pinMode(PWM_DRV_TEC1,OUTPUT);
  pinMode(PWM_DRV_TEC2,OUTPUT);
  pinMode(PWM_PUMP,OUTPUT);
  pinMode(PWM_EMAGNET,OUTPUT);

  //SPI
//  pinMode(AD7124_CS, OUTPUT);
 
  [COLOR="#FF0000"]pinMode(14,OUTPUT);
  pinMode(15,OUTPUT);
  pinMode(16,OUTPUT);
  pinMode(17,OUTPUT);
  
  pinMode(TFT_CS, OUTPUT);[/COLOR]
...

The ones in RED are your CS pins? You set them to OUTPUT so their state will be driven by the pins by whatever default state which I believe is low...
But don't leave it by chancel
Code:
 [COLOR="#FF0000"]
  pinMode(14,OUTPUT); digitalWrite(14, HIGH);
  pinMode(15,OUTPUT); digitalWrite(15, HIGH);
  pinMode(16,OUTPUT);digitalWrite(16, HIGH);
  pinMode(17,OUTPUT);digitalWrite(17, HIGH);
  
  pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH);

[/COLOR]
...
The above if I typed in correctly should set all of them to be inactive...


In most cases, good libraries that use SPI will try to take care of their CS pin and SPI desired settings internally.

So for example if you do something like tft.fillScreen(my_color);
Internally it will in this case call fillRect for the whole screen.
Code:
		beginSPITransaction(_SPI_CLOCK);
		setAddr(x, y, x+w-1, y+h-1);
		writecommand_cont(HX8357_RAMWR);
		for(y=h; y>0; y--) {
			for(x=w; x>1; x--) {
				writedata16_cont(color);
			}
			writedata16_last(color);
		}
		endSPITransaction();
Where the functions beginSPITransaction and endSPITransaction
Will do the SPI.beginTransaction and do the setting of the CS pins.

And my quick look is you are using an Adafruit library to read the MAX... And Their library uses their SPI Device library which also knows about transactions.

So again when you call things like: all_sensors->readInternal())

So their Read internal starts off like:
Code:
double Adafruit_MAX31855::readInternal(void) {
  uint32_t v;

  v = spiread32();
...
And the spiread32 does:
... spi_dev.read(buf, 4);

Which again does:
Code:
bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
  memset(buffer, sendvalue, len); // clear out existing buffer
  if (_spi) {
    _spi->beginTransaction(*_spiSetting);
  }
  digitalWrite(_cs, LOW);
  transfer(buffer, len);
  digitalWrite(_cs, HIGH);

  if (_spi) {
    _spi->endTransaction();
  }

#ifdef DEBUG_SERIAL
  DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
  for (uint16_t i = 0; i < len; i++) {
    DEBUG_SERIAL.print(F("0x"));
    DEBUG_SERIAL.print(buffer[i], HEX);
    DEBUG_SERIAL.print(F(", "));
    if (len % 32 == 31) {
      DEBUG_SERIAL.println();
    }
  }
  DEBUG_SERIAL.println();
#endif

  return true;
}
So again they handle the CS pin and the SPI Settings that they want...

So again other than handling the init to make sure that they don't multiple CS pins asserted at startup time, you should not need to do anything with the CS pins nor with the SPI settings...

As for knowing when SPI.transfer(0xff);
is done. It is done by the time it returns from the call. As it returns the data that was transferred back on the MISO pin...

Only time you need to worry about overlap is IF do something asynchronous.
That is you use the SPI.transfer(buffer, rxBuffer, count, Event);
And then it will be active until the event has been triggered. But that is not happening here.

Likewise if you told the Display to use a frameBuffer and then called updateScreenAync(), which again will be active until the screen completes the update. There are query functions in the library to see if it is done yet or not... But you are not calling that.
 
Hi Kurt,

Thanks for your elaborate answer! I feel stupid.

I had a gut feeling in the beginning looking over the Code, still neglected it and made an assumption.
At the thermocouple1_4 that the pins were set here to high after the loop.

In the Deep recesses of my mind I had a hunch that the digital pins In the beginning were measily defined and leave it by chance. I didn’t learn from previous attempts thanks!

I’ll have to look more careful next time what the other programs are doing.m

Sorry I don’t understand the part with the overlap.
But writing something like 0xff From MOSI to Receive at Miso is not the way to go?

Thanks !
Good night!
 
Hi Kurt,

so I changed in the Init all pins to active HIGH before executing the start programs for the thermocouples and TFT screen. then removed all the digitalWrites to low and high in the Void setup and loop.

in void Setup()
pinMode(14,OUTPUT);digitalWrite(14,HIGH);
pinMode(15,OUTPUT);digitalWrite(15,HIGH);
pinMode(16,OUTPUT);digitalWrite(16,HIGH);
pinMode(17,OUTPUT);digitalWrite(17,HIGH);

pinMode(TFT_CS, OUTPUT);digitalWrite(TFT_CS,HIGH);

for(int i=0;i>4;i++)
{
SPI.beginTransaction(SettingsA);


if (all_sensors->begin())
{
Serial.println("ERROR.");
while (1) delay(10);
}
Serial.println("DONE.");


SPI.endTransaction();
}

SPI.beginTransaction(settingsTFT);

tft.begin();

uint8_t x = tft.readcommand8(HX8357_RDMODE);
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(HX8357_RDMADCTL);
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(HX8357_RDPIXFMT);
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(HX8357_RDIMGFMT);
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(HX8357_RDSELFDIAG);
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

tft.setRotation(1);
tft.fillScreen(C_BLACK);

tft.fillRect(0, 30, 480, 10, C_RED);
tft.fillRect(0, 140, 480, 10, C_BLUE);

SPI.endTransaction();


screen freezes over again.

i removed the flickerfreeprint program to see if the problem goes away. but it does not.
it still freezes over.

I switched the TFT_DC and MAXDO pin from 9 to 10. still the screen freezes over.
here is a print out of the Serial Monitor if

MAXDO is set to 10, and TFT_DC is set to 9.
and also the wires are switched
_t3n::begin mosi:11 miso:12 SCLK:13 CS:8 DC:10 SPI clocks: 26000000 2000000
_t3n::begin - completed

Display Power Mode: 0x8C
MADCTL Mode: 0xC0

Pixel Format: 0x5

Image Format: 0x0

Self Diagnostic: 0xC0

MENU1 set SampleTime

0test TC00.00

test TC10.00

test TC20.00

test TC30.00

Starting MENU1

TC0 pin14 INT 22.94 NOT 17.25

TC1 pin15 INT 25.88 NOT 13.50

TC2 pin16 INT 23.69 NOT 15.50

TC3 pin17 INT 22.94 NOT 16.75

MENU1 set SampleTime
interesting is that the SPI wants to communicate but cannot because of the DC pin? which is bound for both devices? Screen also freezes over.

MAXDO is set to 9, and TFT_DC is set to 10.[/COLOR]
_t3n::begin mosi:11 miso:12 SCLK:13 CS:8 DC:10 SPI clocks: 26000000 2000000
_t3n::begin - completed

Display Power Mode: 0x9C

MADCTL Mode: 0xC0

Pixel Format: 0x0

Image Format: 0x0

Self Diagnostic: 0xC0

MENU1 set SampleTime

0test TC00.00

test TC10.00

test TC20.00

test TC30.00

Starting MENU1

TC0 pin14 INT 23.06 NOT 17.25

TC1 pin15 INT 25.88 NOT 12.25

TC2 pin16 INT 23.44 NOT 15.75

TC3 pin17 INT 23.19 NOT 16.50

please help.

first thumbnail is with the running thermocouples on the background. screen freezes over:

second thumbnail is with the running display and the thermocouples program commented out:

I hope this helps to understand what is going on.
 

Attachments

  • IMG_E3087[1].jpg
    IMG_E3087[1].jpg
    134.2 KB · Views: 103
  • thumbnail2.png
    thumbnail2.png
    397.8 KB · Views: 103
Last edited:
I also tried: because I discovered that the MISO Line for the MAX31855 is not a Data Command line.
all connections are checked 4.7K on the CS pins from VCC to CS for the max31855 and TFT featherwing 3.5"

Code:
/SPI defines
#define MAXCLK 13 //max31855 nothing else.
#define MAXMISO    12// it doesnt matter if this is 12 or 10, has been tested. temperature readouts take place.
#define MAX31855_1 14
#define MAX31855_2 15
#define MAX31855_3 16
#define MAX31855_4 17

#define TFT_DC  9
#define TFT_CS 8
#define TFT_RST -1

display freezes over same as thumbnail 1
Previous Post TFT Screen Image
,

measurement with probe:
oscilloscope measurement MISOpin12.jpg

I posted 2 MISO recordings from the MISO pin 12. the recording is of the two functions 1 is the TFT and the other is the Thermocouple1_4(); i have it floating at 10K voltage divider and see blips around 100ms. the blips are 3ms wide doing a lot of up and downs on the MISO line. MISOLINE_Blip around 100ms..jpgMISOLINE_Blip at 100ms is 3ms long.png

funny thing is if I press the button on the RGB encoder the blips tend to go faster to the left on the oscilloscope.

the long blips are from the Thermocouple1_4() function.

if I comment the
//Thermocouple1_4()
i get data on the screen as before, but the Blips are gone. Commentedout_Thermocouple1_4function.png

love to hear your opinion, answer, hint or anyway how to solve this puzzle.
I hope the information i provided helps to understand the problem better.

best regards

Bastiaan
 
Last edited:
Sorry, but I am not sure how much I can help.

Other than make suggestions on helping you debug it.

Things like: When you say the screen freezes, does that simply mean the screen no longer works and your program is still doing other things? Or does it imply your code is hanging some place?

When it is no longer updating, can you probe and see if any of the CS pins are Asserted (LOW)? If so does it stay asserted or change? Are more than one asserted?

I often times use unused pins, to signal state that I can watch with Logic Analyzer (you can with Scope as well). Things like set a pin high when starting a read of some sensor and set it low when done... (But your CS pins may do some of that for you).

If you can localize down to like it is in reading some sensor, or updating screen or ??? than Either add more digitalWrites of different pins in that function to localize down, or
Serial.print like statements... Note when Serial.print and hangs. I will also add in some Serial.flush() statements to force out the current state, in the case the program totally hangs/crashes.

Sorry hard to know what else to do, but to start narrowing down the problem.

Good Luck
 
Things like: When you say the screen freezes, does that simply mean the screen no longer works and your program is still doing other things? Or does it imply your code is hanging some place?

the screen freezes
the Serial monitor prints out where I am with my encoder push button, and also shows that I am in the TFT function.

in the tft menucountdown() i have the following code:
Code:
if(menuCount>0&&menuCount==1)
{ Serial.println("Starting MENU1");
  //Sample Time
  tft.setTextColor(C_WHITE, C_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10,130);
  tft.print("Variables to SET");
  tft.setTextSize(1);
  tft.setCursor(10,150);
  tft.print(" Setting Variables by rotating enc and press button to save");
  tft.setCursor(10, 170);
  tft.print("1* Samples/sec ");
  tft.print(SampleTime);

shows me on the serial monitor:

Code:
_t3n::begin mosi:11 miso:12 SCLK:13 CS:8 DC:9 SPI clocks: 26000000 2000000
_t3n::begin - completed
Display Power Mode: 0xCE
MADCTL Mode: 0xE0
Pixel Format: 0x2
Image Format: 0x0
Self Diagnostic: 0xE0
MENU1 set SampleTime 
TC00.00
TC20.00
TC20.00
TC30.00
Starting MENU1

When it is no longer updating, can you probe and see if any of the CS pins are Asserted (LOW)? If so does it stay asserted or change? Are more than one asserted?
these are the measured signals just now.
looks nice CS pin redTFT_green_yellow_Blue_max31855.pngmeasuring the CS pins.png

the red one is from the CS pin for the TFT, the yellow blue and green are for the MAX31855
the other one I take for granted because I dont have free Oscilloscope probes (checked also, works fine, same signal shapes)

I often times use unused pins, to signal state that I can watch with Logic Analyzer (you can with Scope as well). Things like set a pin high when starting a read of some sensor and set it low when done... (But your CS pins may do some of that for you).

where shall i use Serial.flush();?

again many thanks!
 
Last edited:
Serial.flush();
Which is the exact same code as : Serial.send_now();

Tells the USB Serial code to send what it has currently in the buffer and not wait until the buffer is full or there is a timeout, which sends it.

Why this is important is... Sometimes you run into cases like:
Code:
if(menuCount>0&&menuCount==1)
{ Serial.println("Starting MENU1");
  //Sample Time
  tft.setTextColor(C_WHITE, C_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10,130);
  tft.print("Variables to SET");

And maybe the next place you call has something like:

Code:
Serial.println("Start XYX");

Which if the last thing you see is: Starting MENU1
You might think means you are still in that function... But maybe the other printed and it has not made its way out before crashing...

So in cases like this I do: Serial.println("Starting MENU1"); Serial.flush();

Which slows the program down slightly but helps to make sure you are where you think you are...

And I would then continue to output additional Serial.prints like at end of the if(...) area
And if it hangs in there add other ones after each graphic primitive... And see if you can get it down to which call fails...
 
Understand. It’s just ackward.

at the beginning during the start up(Without thermocouple function)

The tft screen just shows All the data from the internalADC and the first Line of Menu 1:
If the button from the encoder is pressed it shows menu2, menu3 and so on, on the Screen.

Samples/sec 1000( the thousand is a multiplication from the encoder) it just puts values( well it should) on the Screen

Ill comment out all out of the IF statements and see if it loads the tft.prints.

Because I tried before commenting out the if statements, screen freezes over. So I was guessing the problem was somewhere else. Anyway I’ll try next week again and serial.flush it.

The CS PinS look fine I guess then?

thanks for the hints and tricks!

Best regards and a nice weekend!

Bastiaan
 
Sorry, hope we will figure it out soon.

Debugging things like this can be a real pain... Problem is it is hard for me to help much as I don't have your setup...

So can only help steer you.

The flush() stuff has helped me at times when I would start debugging something only to find out that was not where the problem was...

Have a nice weekend!
 
Hi Kurt E,

so it got stuck at the thermocouple1_4() function, the calls to the class MAX31855 required some settling time.
so I applied millis if statement in between the for loop that calls the class MAX31855.

however next problem:

i have to write the values to the screen they are of the double type and I am having problems with the following:



Code:
void Loop()
{
 double *p=0;
      
      unsigned long TC_currentMillis=millis();
      if(TC_currentMillis-TC_previousMillis>=TC_Interval)
      {
       TC_previousMillis=TC_currentMillis;
       p=Thermocouples1_4();
       Serial.println(p[12]); 
 
      }

      
      unsigned long ScreencurrentMillis=millis();
      if(ScreencurrentMillis-ScreenpreviousMillis>=ScreenInterval)
      {
        ScreenpreviousMillis=ScreencurrentMillis;
        TFTscreen(p);  
          
      }

}

both functions are now closed off Void TFTscreen(double p) function
and *Thermocouples1_4() is a pointer function, which gives back an Array[12] values 4 for the Negative, internal, Positive values.
i have written down the code in red and would like to have a second opinion if the way how I did it why it doesnt work.

Code:
[COLOR="#FF0000"]void *Thermocouples1_4() [/COLOR]//see instantiation pointer to array class TH1,TH2,TH3,TH4
{
     SPI.beginTransaction(SettingsA);
     

     for(int i=0;i<12;i++)
     {

   
//     Serial.print("TC");
//     Serial.print(i);
//     Serial.print(" pin");
//     Serial.print(14+i);
//     Serial.print(" INT ");
     
      unsigned long TC_currentMillis=millis();
      if(TC_currentMillis-TC_previousMillis>=TC_Interval)
      {
       TC_previousMillis=TC_currentMillis;
   
     if(all_sensors[i]->readCelsius()<0)//if temperature is lower than 0   ////Thermocouple 1
     {
     c[i] = all_sensors[i]->readCelsius();
     c[i+4]=all_sensors[i]->readInternal();
     Serial.print("INTERNAL");
     Serial.println(c[i+4]);
     Serial.print(" Measured ");
     Serial.println(c[i]);
     
     double SubC1_int=c[i]-c[i+4];
     double SubCalc=SubC1_int*0.041276; /*mV*/
     double E1=(-0.176*pow(10,-1));
     double E2=(0.389*pow(10,-1)*pow(c[i+4],1));
     double E3=(0.186*pow(10,-4)*pow(c[i+4],2));
     double E4=(-0.995*pow(10,-7)*pow(c[i+4],3));
     double E5=(0.318*pow(10,-9)*pow(c[i+4],4));
     double E6=(-0.561*pow(10,-12)*pow(c[i+4],5));
     double E7=(0.561*pow(10,-15)*pow(c[i+4],6));
     double E8=(-0.320*pow(10,-18)*pow(c[i+4],7));
     double E9=(0.972*pow(10,-22)*pow(c[i+4],8));
     double E10=(-0.121*pow(10,-25)*pow(c[i+4],9));
     double E11=(0.119*pow(exp(-0.118*pow(10,-3)*(c[i+4]-0.127*pow(10,3))),2));
     double E1_11=E1+E2+E3+E4+E5+E6+E7+E8+E9+E10+E11;
     double AddCJError=E1_11+SubCalc;
     double R1=0+(2.51734*pow(AddCJError,1));
     double R2=(-1.17*pow(AddCJError,2));
     double R3=(-1.08*pow(AddCJError,3));
     double R4=(-8.977*pow(10,-1)*pow(AddCJError,4));
     double R5=(-3.73*10*pow(10,-1)*pow(AddCJError,5));
     double R6=(-8.6632*pow(10,-2)*pow(AddCJError,6));
     double R7=(-1.045*pow(10,-2)*pow(AddCJError,7));
     double R8=(-5.1920577*pow(10,-4)*pow(AddCJError,8));
     double R9=0*pow(AddCJError,9);
     double R1_9=R1+R2+R3+R4+R5+R6+R7+R8+R9;
     Serial.print("Cold ");
     Serial.print("Corr Value ");
     c[i]=(double)R1_9;
     
     if (isnan(c[i])) {
       Serial.print("Something wrong with Thermocouple ");
  
     } 
     else {
       Serial.print("C = ");
       Serial.println(c[i]);
     }
     }
     else //this is the 0...500°
     {
     
     c[i+4]=all_sensors[i]->readInternal();
     c[i+8]= all_sensors[i]->readCelsius();

     
     //----------------------------------------------------------------------------------
     
      }
    return c;
    }
     //this is an array containing negative temperature c[i]values, internal temperaturec[i+4], and positive Temperature c[i+8].
    SPI.endTransaction();
 
  }//millis
//thermocuple function 

}



Code:
[COLOR="#FF0000"]void TFTscreen(double *p) /[/COLOR]/Menu 1 //Display
{
// get some data
     j += 0.0013;
   currentmicros = micros();
    long value;
  double voltage;
  
 /* all graphics commands have to appear within the loop body. */    
       SPI.beginTransaction(settingsTFT);
      
      
      Data1.setTextColor(C_WHITE, C_BLACK);
      tft.setTextSize(2);
      tft.setCursor(0, 0);
      tft.print("Emagnet program");
      Data1.print(j,2);
    //  // now let's see the tft update with FlickerFree
      tft.setTextSize(1);
      tft.setCursor(0,20);
      Data1.setTextColor(C_WHITE, C_BLACK);
      tft.print("Temperature readout");
      tft.print(" Voltages from Thermocouples ");
      tft.setTextSize(2);
      Data1.setTextColor(C_WHITE, C_BLACK);
      tft.setCursor(20,45);
      Data1.print(j,2);
[COLOR="#FF0000"]      sprintf(str,"TempEmag: %.2lf\n",p[0]);[/COLOR]
      Data1.print(str);
      tft.setCursor(20,60);
      Data1.print(c[0]); //C is a global variable!

      Data1.print(j,2);
      tft.setCursor(20,75);
[COLOR="#FF0000"]      sprintf(str,"TempWater: %.2lf\n",p[1]);[/COLOR]
      Data1.print(str);
     
      Data1.print(j,2);
      tft.setCursor(20,90);
    [COLOR="#FF0000"]  sprintf(str,"TempTEC2: %.2lf\n",p[2]);[/COLOR]
      Data1.print(str);
      
      Data1.print(j,2);
      tft.setCursor(20,105);
[COLOR="#FF0000"]      sprintf(str,"Temp: %.2lf\n",p[3]);[/COLOR]
      Data1.print(str);
    
      tft.print(c[3]);
      tft.print(" C");
      tft.setCursor(20,120);
      tft.setTextSize(2);
      tft.setCursor(250,45);
      tft.print("Currents");
      tft.setTextSize(2);
      tft.setCursor(250,60);
      Data1.print(TEC1Current);
      tft.print("A");
      tft.setCursor(250,75);
      Data1.print(TEC2Current);
     tft.print("A");
     tft.setCursor(250,90);
      Data1.print(PumpCurrent);
      tft.print("A");
      tft.setCursor(250,105);
      Data1.print(EMAGCurrent);
      tft.print("A");
 
Sorry, I don't do much floating point output, to know if there is anything better to convert doubles to strings...

Althought I believe you can do something like tft.print(*p, 21);

And if you are going to use something like sprintf, there many would recommend using snprintf instead as to make sure you don't overrun the size of your str array.
 
Ok Good hint! Thanks Kurt E,

I am not getting the doubles from a void pointer function to a TFTscreen(p);
how can I show values inside the function TFTScreen() and Serial.print it.?


That was my kind of actual question:)

If I serial print in the void loop p=thermocouple();
I can see the various values from the array By for looping it with p;

However I am getting zeros in the void TFTScreen(Double *p)
Why is that?
 
Second question:

what would be the best approach in using no delay with millis.
On the TFT screen ?

i have in total 4 if statements with no delay millis, i don’t know what is the best approach.

I have one for internalADC, menucheck, TFTscreen total, and for the thermocouples 2 seperate ones
 
Ok Good hint! Thanks Kurt E,

I am not getting the doubles from a void pointer function to a TFTscreen(p);
how can I show values inside the function TFTScreen() and Serial.print it.?


That was my kind of actual question:)

If I serial print in the void loop p=thermocouple();
I can see the various values from the array By for looping it with p;

However I am getting zeros in the void TFTScreen(Double *p)
Why is that?


Sorry, but I have no idea of what you are saying here. Likewise I have no idea on how/if your code would work. That is:
Code:
void Loop()
{
 double *p=0;
      
      unsigned long TC_currentMillis=millis();
      if(TC_currentMillis-TC_previousMillis>=TC_Interval)
      {
       TC_previousMillis=TC_currentMillis;
       p=Thermocouples1_4();
       Serial.println(p[12]); 
 
      }

      
      unsigned long ScreencurrentMillis=millis();
      if(ScreencurrentMillis-ScreenpreviousMillis>=ScreenInterval)
      {
        ScreenpreviousMillis=ScreencurrentMillis;
        TFTscreen(p);  
          
      }

}

You define p as a pointer to a double value and assign it 0 (so it is a NULL ptr). You do assign something to that pointer from the return of: p=Thermocouples1_4();
You play around in that function with some array c? Where is that defined? ... If you wish to have that one return a double, than return a double? Now a pointer (void *)... Again hard to say what is going on... But as always probably keep it simple...


Second question:

what would be the best approach in using no delay with millis.
On the TFT screen ?

i have in total 4 if statements with no delay millis, i don’t know what is the best approach.

I have one for internalADC, menucheck, TFTscreen total, and for the thermocouples 2 seperate ones

Again your question is unclear. I think you are asking how to have different things run at different intervals. Like the stuff:
Code:
      unsigned long ScreencurrentMillis=millis();
      if(ScreencurrentMillis-ScreenpreviousMillis>=ScreenInterval)
I personally prefer to use specific sized variables like uint32_t instead of unsigned long but in this case same size...
You can also use the built int class (elapsedMillis to do some of this.)

Which more or less does the same thing.

That is somewhere you define it, like: elapsedMillis emScreenInterval;
Code:
      if(emScreenInterval>=TC_Interval)
      {
       emScreenInterval = 0;
       p=Thermocouples1_4();
       Serial.println(p[12]); 
 
      }
 
I want to write closed functions that are of void type.

https://forum.pjrc.com/threads/6324...s-to-closed-void-functions?highlight=max31855

Maybe this link explains it better


Best

Bastiaan

Sorry, but I have no idea of what you are saying here. Likewise I have no idea on how/if your code would work. That is:
Code:
void Loop()
{
 double *p=0;
      
      unsigned long TC_currentMillis=millis();
      if(TC_currentMillis-TC_previousMillis>=TC_Interval)
      {
       TC_previousMillis=TC_currentMillis;
       p=Thermocouples1_4();
       Serial.println(p[12]); 
 
      }
      
      unsigned long ScreencurrentMillis=millis();
      if(ScreencurrentMillis-ScreenpreviousMillis>=ScreenInterval)
      {
        ScreenpreviousMillis=ScreencurrentMillis;
        TFTscreen(p);  
          
      }

}

You define p as a pointer to a double value and assign it 0 (so it is a NULL ptr). You do assign something to that pointer from the return of: p=Thermocouples1_4();
You play around in that function with some array c? Where is that defined? ... If you wish to have that one return a double, than return a double? Now a pointer (void *)... Again hard to say what is going on... But as always probably keep it simple...




Again your question is unclear. I think you are asking how to have different things run at different intervals. Like the stuff:
Code:
      unsigned long ScreencurrentMillis=millis();
      if(ScreencurrentMillis-ScreenpreviousMillis>=ScreenInterval)
I personally prefer to use specific sized variables like uint32_t instead of unsigned long but in this case same size...
You can also use the built int class (elapsedMillis to do some of this.)

Which more or less does the same thing.

That is somewhere you define it, like: elapsedMillis emScreenInterval;
Code:
      if(emScreenInterval>=TC_Interval)
      {
       emScreenInterval = 0;
       p=Thermocouples1_4();
       Serial.println(p[12]); 
 
      }
 
Personally I think this is barking up the wrong tree! void *
To me says kick me, kick me... That is there is no type checking or anything else to help make sure your are passing the right type of variables to the different places...

If you have not done so, I would always have the Arduino compiler output as much warnings as possible... That is go into preferences and make sure compiler wanings is set to ALL.

And then look at each Warning and try resolve them.

Also I try to avoid long term usage of variable names like: p
What is p? Is it an array? Is it of thermocouple values... Again personally prefer names that have some meaning.
 
Ok Good Point:)

sure I’ll change that for sure:)

i had to laugh about this.

:) thanks Kurt I’ll clean it up

Best regards

Personally I think this is barking up the wrong tree! void *
To me says kick me, kick me... That is there is no type checking or anything else to help make sure your are passing the right type of variables to the different places...

If you have not done so, I would always have the Arduino compiler output as much warnings as possible... That is go into preferences and make sure compiler wanings is set to ALL.

And then look at each Warning and try resolve them.

Also I try to avoid long term usage of variable names like: p
What is p? Is it an array? Is it of thermocouple values... Again personally prefer names that have some meaning.
 
Status
Not open for further replies.
Back
Top