Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Embedded project needs devices which can work continuously at +125 degree C

Status
Not open for further replies.
Regarding post #60 do I need an external Crystal at T1OSO/OSI pins so that I can make PIC wakeup from sleep using Timer1 ? By enabling T1OSCEN_bit ?
 

We used Idle mode instead of sleep mode.

I have a new question. Find the attached latest schematic (TMS-MB-SSL4.PDF). We had to revert back to MAX31855 and MUXs as PCB manufacturer was not able to pick and place 3mm X 3mm MAX31850KATB+ and also solder it.

For our new design I want to know whether I have to put individual pull-ups on

1. MAX31855 SCK line
2. MAX31855 SO (SOx) line
3. MAX31855 CS (CSx) line
4. MUX1 SO line
5. MUX2 CS line

Edit:

Refer TMS-MB-SSL5.PDF

I have added pull-ups on SCK, SO and CS lines. Are these enough ?
 

Attachments

  • TMS-MB-SSL4.PDF
    50.2 KB · Views: 91
  • TMS-MB-SSL5.PDF
    50.8 KB · Views: 70

You only need one pull-up on each shared line. I'm not sure why you use the 74HC151 like that, to me it would make more sense to use a 3 to 8 decoder (74HC138 for example) and use it to select one of the eight thermocouple amplifiers at a time. Maybe there is more to the circuit than shown but it appears you are driving the CS signal 'backwards' to me.

Do you really need to put the PIC to sleep between 'wake up calls'? In low power mode you can leave it running and still only draw a few uA of supply current. I would suggest you put as much of the remaining circuitry to sleep if possible but leave the PIC running on its internal oscillator. If you create the required delay in an interrupt driven timing routine you can power everything up, do the work and shut down again to save power. On most PICs you can software configure the internal clock divider so you can run it at low speed to do the timing delay then switch to full speed to do the work.

Brian.
 
Can you show how I can use 74HC138 to select one TC amplifier at a time ? I am not getting it. SCK line is common to all but CS and SO pins are different. Are you telling that I can connect SCK and SO lines of the TC amplifiers to 2 pins of PIC and just select the 74HC138 to select only the CS lines of 8 TC amplifiers ?
 

Are you telling that I can connect SCK and SO lines of the TC amplifiers to 2 pins of PIC and just select the 74HC138 to select only the CS lines of 8 TC amplifiers?
That's how SPI bus works. Review the interface description in datasheet, SO has internal tri-state driver enabled by CS.
 

@FvM

But where does the 8x CSx lines output come out of 74HC138 ? Which pin of 74HC138 I have to connect to PIC to control CS lines ?

Is this correct ? Check the attached circuit and reply.
 

Attachments

  • TMS-MB1.PDF
    49.6 KB · Views: 64
Last edited:

The MAXIM data sheet explains the interface, it is basically SPI with no data input pin as the device is read only.

The SCK is always an input to the device and you can share the same signal across many of them.

The CS pin is an input to the device, it enables the SO pin which otherwise is tri-stated. This all the SO pins can share one connection.

The SO pin carries 14 or 32 bits of data, clocked by the SCK signal. D0 is first and follows the first SCK after the IC is selected.

So you can join all the SCK pins together and join all the SO pins together but you still need to drive a CS signal to each device. If your PIC software ignores anything on the pin SO is connected to, you can leave one of the CS signals active all the time, this means all you have to do is send the binary bits to select one of the MAX devices then send SCK pulses and at the same time read back the SO signal. You do need to be careful with the timing but that is a software issue, you just have to make sure SCK doesn't change between selecting a device and starting to read it.

When CS is high at any of the MAXIM devices, it disconnects its SO pin so as long as only one device has CS low at a time, they will not interfere with each other.

On your schematic it appears you are trying to use a 74HC151 to route the CS from the PIC to one of the devices, it will not work simply because the '151 works the other way around, it has 8 inputs and one output. The 74HC138 is a one-of-eight decoder, you give it a three bit selection code and one of the eight outputs goes low, the others go high. That is exactly what you need to select the MAXIM devices. You can leave the HC138's own enables permanently active.

Brian.
 
@ betwixt and FvM

Got it.

And I need 8x pullup resistors on the 8x CSx lines when 74HC138 is used ?
 

Hi,

And I need 8x pullup resistors on the 8x CSx lines when 74HC138 is used ?

No, because the HC138 outputs are push/pull and never high-Z.

Klaus
 
Any problem if I put pullup resistors on 8x CSx lines when 74HC138 is used ?
 

Hi,

Any problem if I put pullup resistors on 8x CSx lines when 74HC138 is used ?
No problem. It´s just useless.

Klaus
 
Please check circuit in page no. 13/22. In the power supply filter circuits for C7 and C8 it is mentioned (NC) Not connected. Can I omit them from my circuit ?
 

Attachments

  • esp-wroom-02d_esp-wroom-02u_datasheet_en-1365835.pdf
    1.1 MB · Views: 58

They are optional but I would fit them if possible. They should be as close to the Wroom as possible and be SMD or short wire through hole parts. They are there because the current drawn by the module can vary from just a few mA to 500mA very quickly as it transmits bursts of data, they help to prevent the supply dipping as the current increases because of impedances in the supply wiring. In essence, they work like small rechargeable batteries right at the place the power is needed so they can maintain the voltage under sudden load increases.

Brian.
 
This is my current code to read MAX31855 but in Proteus simulation I am getting only 0.00 for all TC (thermocouple) readings. What is the problem with the code ?

Also I want to know if I should get TC temperature and also ambient temperatures from the MAX31855.

Code:
sbit On_Off_1 at LATC0_bit;
sbit On_Off_1_Direction at TRISC0_bit;

sbit On_Off_2 at LATC1_bit;
sbit On_Off_2_Direction at TRISC1_bit;

sbit Fan at LATC2_bit;
sbit Fan_Direction at TRISC2_bit;

sbit SCLK at LATE0_bit;
sbit SCLK_Direction at TRISE0_bit;

sbit SO at RE1_bit;
sbit SO_Direction at TRISE1_bit;

sbit MUX_A at LATD0_bit;
sbit MUX_A_Direction at TRISD0_bit;

sbit MUX_B at LATD1_bit;
sbit MUX_B_Direction at TRISD1_bit;

sbit MUX_C at LATD2_bit;
sbit MUX_C_Direction at TRISD2_bit;

sbit MUX_E1 at LATD3_bit;
sbit MUX_E1_Direction at TRISD3_bit;

#define Peltier_Voltage           0
#define Battery_Voltage           1
#define Device_Temperature_Sensor 2

#define Dummy_Adc_Value 1024

#define g_isDeviceConfigured_Flag_Address 0x10

#define True  1
#define False 0

#define On  1
#define Off 0

#define Low  0
#define High 1

#define Input  1
#define Output 0

#define Max_Device_Temperature 150.0

#define Adc_Resolution 1023

#define Regulator_Circuit_Diode_Drop 0.6

#define Minimum_Peltier_Voltage 10.0
#define Minimum_Battery_Voltage  6.6
#define Minimum_Input_Voltage    8.4

#define Peltier_Voltage_Hysterisis 0.5
#define Battery_Voltage_Hysterisis 0.5

typedef struct {
    double g_maxPeltierVoltage;
    double g_maxBatteryVoltage;
}DEVICE_CONFIGURATION_TYPE;

typedef struct {
    unsigned int g_rawAdcValue[3];
    unsigned int g_oldRawAdcValue[3];
    double g_peltierVoltage;
    double g_regulatorInputVoltage;
    double g_batteryVoltage;
    double g_deviceTemperature;
}ADC_TYPE;

typedef struct {
    char g_uartRead;
    char g_uartBuffer[100];
}UART1_TYPE;

typedef struct {
    char g_uartRead;
    char g_uartBuffer[100];
}UART2_TYPE;

typedef struct {
    DEVICE_CONFIGURATION_TYPE deviceConfig;
    ADC_TYPE adc;
    UART1_TYPE uart1;
    UART2_TYPE uart2;
    char i;
    char msg[23];
    unsigned long temp[8];
    double temperature[8];
}TMS_TYPE;

TMS_TYPE tms;

unsigned char flagRegister1 = 0;
unsigned char flagRegister2 = 0;

sbit g_isDeviceConfigured at flagRegister1.B0;
sbit g_deviceSleeping at flagRegister1.B1;

//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms

//Place/Copy this part in declaration section
void InitTimer1() {
    T1CON = 0x31;
    TMR1IF_bit = 0;
    TMR1H = 0x0B;
    TMR1L = 0xDC;
    TMR1IE_bit = 1;
}

void interrupt() {
    if((RC1IE_bit) && (RC1IF_bit)) {
        if(g_deviceSleeping == True) {
            tms.uart1.g_uartRead = UART1_Read();
            g_deviceSleeping = False;
        }
        else {
        
        }
    }
    
    if((RC2IE_bit) && (RC2IF_bit)) {
        if(g_deviceSleeping == True) {
            tms.uart2.g_uartRead = UART2_Read();
            g_deviceSleeping = False;
        }
        else {

        }
    }
    
    if((TMR1IE_bit) && (TMR1IF_bit)) {
        TMR1IF_bit = 0;
        TMR1H = 0x0B;
        TMR1L = 0xDC;
        
        if(g_deviceSleeping == True) {
            g_deviceSleeping = False;
        }
        else {

        }
    }
    
    if((INT0IE_bit) && (INT0IF_bit)) {
        INT0IF_bit = 0;
       
        if(g_deviceSleeping == True) {
            g_deviceSleeping = False;
        }
        else {

        }
    }
}

void initializePorts() {
    On_Off_1_Direction = Output;
    On_Off_2_Direction = Output;
    Fan_Direction = Output;
    SCLK_Direction = Output;
    SO_Direction = Input;
    
    MUX_A_Direction = Output;
    MUX_B_Direction = Output;
    MUX_C_Direction = Output;
    MUX_E1_Direction = Output;
    
    On_Off_1 = Off;
    On_Off_2 = Off;
    Fan = On;
    SCLK = Low;

    MUX_A = Low;
    MUX_B = Low;
    MUX_C = Low;
    MUX_E1 = Low;
}

void initializeVariables() {
    tms.adc.g_rawAdcValue[0] = 0;
    tms.adc.g_oldRawAdcValue[0] = Dummy_Adc_Value;
    
    tms.adc.g_rawAdcValue[1] = 0;
    tms.adc.g_oldRawAdcValue[1] = Dummy_Adc_Value;
    
    tms.adc.g_rawAdcValue[2] = 0;
    tms.adc.g_oldRawAdcValue[2] = Dummy_Adc_Value;
    
    tms.adc.g_peltierVoltage = 0.0;
    tms.adc.g_batteryVoltage = 0.0;
    tms.adc.g_deviceTemperature = 0.0;
}

double readMax31855(char channel) {
    char i = 0;
    unsigned long result = 0;
    double centigrade = 0.0;
    
    MUX_E1 = Low;
    
    if((channel >= 1) && (channel <= 8)) {
        channel = channel - 1;
        
        MUX_A = channel.B0;
        MUX_B = channel.B1;
        MUX_C = channel.B2;
        MUX_E1 = High;
        Delay_us(50);
    }
    
    for(i = 0; i < 32; i++) {
        SCLK = High;
        Delay_us(20);
        if(SO)result = result | 1;
        SCLK = Low;
        Delay_us(20);
        
        result <<= 1;
    }
    
    MUX_E1 = Low;
    
    if(result & 0x80000000) {
        // Negative value, drop the lower 18 bits and explicitly extend sign bits.
        result = 0xFFFFC000 | ((result >> 18) & 0x00003FFFF);
    }
    else {
        // Positive value, just drop the lower 18 bits.
        result >>= 18;
    }

    centigrade = (double)result;

    return centigrade;
}

void main() {

    asm clrwdt
    OSCCON = 0x57;
    OSCCON2 = 0x83;
    OSCTUNE = 0x00;
    
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;

    SLRCON = 0x00;

    ANSELA = 0x07;
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    ANSELE = 0x00;

    TRISA = 0x07;
    TRISB = 0x01;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;

    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;

    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

    UART1_Init(9600);
    UART2_Init(9600);
    Delay_ms(200);
    
    //g_isDeviceConfigured = EEPROM_Read(g_isDeviceConfigured_Flag_Address);
    Delay_ms(20);
    
    initializePorts();
    
    g_isDeviceConfigured = True;
    
    if(g_isDeviceConfigured == True) {
       INTEDG0_bit = 0;
       INT0IF_bit = 0;
       INT0IE_bit = 1;
       
       InitTimer1();
       INTCON |= 0xC0;
    }

    while(1) {
         asm clrwdt
         
         if(g_isDeviceConfigured == True) {
              tms.adc.g_rawAdcValue[0] = (unsigned int)ADC_Read(Peltier_Voltage);
              Delay_us(20);
              tms.adc.g_rawAdcValue[1] = (unsigned int)ADC_Read(Battery_Voltage);
              Delay_us(20);
              tms.adc.g_rawAdcValue[2] = (unsigned int)ADC_Read(Device_Temperature_Sensor);
              Delay_us(20);
              
              if(tms.adc.g_rawAdcValue[0] != tms.adc.g_oldRawAdcValue[0]) {
                 tms.adc.g_peltierVoltage = (double)tms.adc.g_rawAdcValue[0] * tms.deviceConfig.g_maxPeltierVoltage / Adc_Resolution;
                 tms.adc.g_regulatorInputVoltage = tms.adc.g_peltierVoltage - Regulator_Circuit_Diode_Drop;
                 tms.adc.g_rawAdcValue[0] = tms.adc.g_oldRawAdcValue[0];
              }
              
              if(tms.adc.g_rawAdcValue[1] != tms.adc.g_oldRawAdcValue[1]) {
                 tms.adc.g_batteryVoltage = (double)tms.adc.g_rawAdcValue[1] * tms.deviceConfig.g_maxBatteryVoltage / Adc_Resolution;
                 tms.adc.g_rawAdcValue[1] = tms.adc.g_oldRawAdcValue[1];
              }
              
              if(tms.adc.g_rawAdcValue[2] != tms.adc.g_oldRawAdcValue[2]) {
                 tms.adc.g_peltierVoltage = (double)tms.adc.g_rawAdcValue[2] * Max_Device_Temperature / Adc_Resolution;
                 tms.adc.g_rawAdcValue[2] = tms.adc.g_oldRawAdcValue[2];
              }
              
              if(tms.adc.g_peltierVoltage <= Minimum_Peltier_Voltage) {
              
              }
              
              for(tms.i = 0; tms.i < 8; tms.i++) {
                  sprintf(tms.msg,"TC%u = %5.2f\r\n",tms.i, readMax31855(tms.i + 1));
                  UART2_Write_Text(tms.msg);
              }
         }
         else {
         
         }
         
         if(g_deviceSleeping == 0) {
            //BAUDCON1.WUE = 1;
            //BAUDCON2.WUE = 1;
            
            g_deviceSleeping = 1;
            //asm sleep
         }
    }
}

Simulation result (see attached).

Schematic attached (PDF).
 

Attachments

  • TMS-MB-SIM-v1.2.PDF
    53.4 KB · Views: 72
  • SIM-SS1.png
    SIM-SS1.png
    77.9 KB · Views: 95

Hi,

usually the SS signal of the SPI interface is LOW-active.

Thus I recommend to use it this standard way.
* at the microcontroller hardware side you don´t need to change anything.
* you may rename the signal to "!SS" (just to be the standard name)
* at U17 move the signal from pin6 to pin5, and pull pin6 HIGH
* add a pullup at the "!SS" signal to disable all devices as long as the microcontroller is not operating.

Klaus
 
Which is !SS signal ? !CSx signals ? If yes, I need 8x pullup resistors ?

Not working yet.

You mean I have to modify circuit like in attached PDF ?

Still not working.

This is the latest code.

Code:
sbit On_Off_1 at LATC0_bit;
sbit On_Off_1_Direction at TRISC0_bit;

sbit On_Off_2 at LATC1_bit;
sbit On_Off_2_Direction at TRISC1_bit;

sbit Fan at LATC2_bit;
sbit Fan_Direction at TRISC2_bit;

sbit SCLK at LATE0_bit;
sbit SCLK_Direction at TRISE0_bit;

sbit SO at RE1_bit;
sbit SO_Direction at TRISE1_bit;

sbit MUX_A at LATD0_bit;
sbit MUX_A_Direction at TRISD0_bit;

sbit MUX_B at LATD1_bit;
sbit MUX_B_Direction at TRISD1_bit;

sbit MUX_C at LATD2_bit;
sbit MUX_C_Direction at TRISD2_bit;

sbit MUX_E1 at LATD3_bit;
sbit MUX_E1_Direction at TRISD3_bit;

#define Peltier_Voltage           0
#define Battery_Voltage           1
#define Device_Temperature_Sensor 2

#define Dummy_Adc_Value 1024

#define g_isDeviceConfigured_Flag_Address 0x10

#define True  1
#define False 0

#define On  1
#define Off 0

#define Low  0
#define High 1

#define Input  1
#define Output 0

#define Max_Device_Temperature 330.0

#define Adc_Resolution 1023

#define Regulator_Circuit_Diode_Drop 0.6

#define Minimum_Peltier_Voltage 10.0
#define Minimum_Battery_Voltage  6.6
#define Minimum_Input_Voltage   10.0

#define Max_Peltier_Voltage 20.0
#define Max_Battery_Voltage  8.4

#define Peltier_Voltage_Hysterisis 0.5
#define Battery_Voltage_Hysterisis 0.5

typedef struct {
    double g_maxPeltierVoltage;
    double g_maxBatteryVoltage;
}DEVICE_CONFIGURATION_TYPE;

typedef struct {
    unsigned int g_rawAdcValue[3];
    unsigned int g_oldRawAdcValue[3];
    double g_peltierVoltage;
    double g_regulatorInputVoltage;
    double g_batteryVoltage;
    double g_deviceTemperature;
}ADC_TYPE;

typedef struct {
    char g_uartRead;
    char g_uartBuffer[100];
}UART1_TYPE;

typedef struct {
    char g_uartRead;
    char g_uartBuffer[100];
}UART2_TYPE;

typedef struct {
    DEVICE_CONFIGURATION_TYPE deviceConfig;
    ADC_TYPE adc;
    UART1_TYPE uart1;
    UART2_TYPE uart2;
    char i;
    char msg[23];
    unsigned long temp[8];
    double temperature[8];
}TMS_TYPE;

TMS_TYPE tms;

unsigned char flagRegister1 = 0;
unsigned char flagRegister2 = 0;

sbit g_isDeviceConfigured at flagRegister1.B0;
sbit g_deviceSleeping at flagRegister1.B1;

//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms

//Place/Copy this part in declaration section
void InitTimer1() {
    T1CON = 0x31;
    TMR1IF_bit = 0;
    TMR1H = 0x0B;
    TMR1L = 0xDC;
    TMR1IE_bit = 1;
}

void interrupt() {
    if((RC1IE_bit) && (RC1IF_bit)) {
        if(g_deviceSleeping == True) {
            tms.uart1.g_uartRead = UART1_Read();
            g_deviceSleeping = False;
        }
        else {
        
        }
    }
    
    if((RC2IE_bit) && (RC2IF_bit)) {
        if(g_deviceSleeping == True) {
            tms.uart2.g_uartRead = UART2_Read();
            g_deviceSleeping = False;
        }
        else {

        }
    }
    
    if((TMR1IE_bit) && (TMR1IF_bit)) {
        TMR1IF_bit = 0;
        TMR1H = 0x0B;
        TMR1L = 0xDC;
        
        if(g_deviceSleeping == True) {
            g_deviceSleeping = False;
        }
        else {

        }
    }
    
    if((INT0IE_bit) && (INT0IF_bit)) {
        INT0IF_bit = 0;
       
        if(g_deviceSleeping == True) {
            g_deviceSleeping = False;
        }
        else {

        }
    }
}

void initializePorts() {
    On_Off_1_Direction = Output;
    On_Off_2_Direction = Output;
    Fan_Direction = Output;
    SCLK_Direction = Output;
    SO_Direction = Input;
    
    MUX_A_Direction = Output;
    MUX_B_Direction = Output;
    MUX_C_Direction = Output;
    MUX_E1_Direction = Output;
    
    On_Off_1 = Off;
    On_Off_2 = Off;
    Fan = On;
    SCLK = Low;

    MUX_A = Low;
    MUX_B = Low;
    MUX_C = Low;
    MUX_E1 = Low;
}

void initializeVariables() {
    tms.adc.g_rawAdcValue[0] = 0;
    tms.adc.g_oldRawAdcValue[0] = Dummy_Adc_Value;
    
    tms.adc.g_rawAdcValue[1] = 0;
    tms.adc.g_oldRawAdcValue[1] = Dummy_Adc_Value;
    
    tms.adc.g_rawAdcValue[2] = 0;
    tms.adc.g_oldRawAdcValue[2] = Dummy_Adc_Value;
    
    tms.adc.g_peltierVoltage = 0.0;
    tms.adc.g_batteryVoltage = 0.0;
    tms.adc.g_deviceTemperature = 0.0;
}

double readMax31855(char channel) {
    char i = 0;
    unsigned long result = 0;
    double centigrade = 0.0;
    
    MUX_E1 = Low;
    
    if((channel >= 1) && (channel <= 8)) {
        channel = channel - 1;
        
        MUX_A = channel.B0;
        MUX_B = channel.B1;
        MUX_C = channel.B2;
        MUX_E1 = High;
        Delay_us(5);
    }
    
    SCLK = Low;
    Delay_ms(1);
    
    for(i = 0; i < 32; i++) {
        SCLK = Low;
        Delay_us(20);
        result <<= 1;
        if(SO)result |= 1;
        SCLK = High;
        Delay_us(20);
    }
    
    MUX_E1 = Low;
    
    if(result & 0x80000000) {
        // Negative value, drop the lower 18 bits and explicitly extend sign bits.
        result = 0xFFFFC000 | ((result >> 18) & 0x00003FFFF);
    }
    else {
        // Positive value, just drop the lower 18 bits.
        result >>= 18;
    }

    centigrade = (double)result;

    return centigrade;
}

void main() {

    asm clrwdt
    OSCCON = 0x57;
    OSCCON2 = 0x83;
    OSCTUNE = 0x00;
    
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;

    SLRCON = 0x00;
    
    ADCON1 = 0x80;
    ADCON2 = 0b10110101;

    ANSELA = 0x07;
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    ANSELE = 0x00;

    TRISA = 0x07;
    TRISB = 0x01;
    TRISC = 0xC0;
    TRISD = 0xC0;
    TRISE = 0x00;

    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;

    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

    initializePorts();
    
    UART1_Init(9600);
    UART2_Init(9600);
    Delay_ms(200);
    
    //g_isDeviceConfigured = EEPROM_Read(g_isDeviceConfigured_Flag_Address);
    Delay_ms(20);
    
    g_isDeviceConfigured = True;
    
    if(g_isDeviceConfigured == True) {
       INTEDG0_bit = 0;
       INT0IF_bit = 0;
       INT0IE_bit = 1;
       
       RC1IE_bit = 1;
       RC2IE_bit = 1;
       //InitTimer1();
       //INTCON |= 0xC0;
    }

    while(1) {
         asm clrwdt
         
         if(g_isDeviceConfigured == True) {
              tms.adc.g_rawAdcValue[0] = (unsigned int)ADC_Read(Peltier_Voltage);
              Delay_us(20);
              tms.adc.g_rawAdcValue[1] = (unsigned int)ADC_Read(Battery_Voltage);
              Delay_us(20);
              tms.adc.g_rawAdcValue[2] = (unsigned int)ADC_Read(Device_Temperature_Sensor);
              Delay_us(20);
              
              if(tms.adc.g_rawAdcValue[0] != tms.adc.g_oldRawAdcValue[0]) {
                 tms.adc.g_peltierVoltage = (double)tms.adc.g_rawAdcValue[0] * Max_Peltier_Voltage / Adc_Resolution;
                 tms.adc.g_regulatorInputVoltage = tms.adc.g_peltierVoltage - Regulator_Circuit_Diode_Drop;
                 sprintf(tms.msg,"PV = %4.2f\r\n", tms.adc.g_peltierVoltage);
                 UART2_Write_Text(tms.msg);
                 tms.adc.g_rawAdcValue[0] = tms.adc.g_oldRawAdcValue[0];
              }
              
              if(tms.adc.g_rawAdcValue[1] != tms.adc.g_oldRawAdcValue[1]) {
                 tms.adc.g_batteryVoltage = (double)tms.adc.g_rawAdcValue[1] * Max_Battery_Voltage / Adc_Resolution;
                 sprintf(tms.msg,"DT = %4.2f\r\n", tms.adc.g_batteryVoltage);
                 UART2_Write_Text(tms.msg);
                 tms.adc.g_rawAdcValue[1] = tms.adc.g_oldRawAdcValue[1];
              }
              
              if(tms.adc.g_rawAdcValue[2] != tms.adc.g_oldRawAdcValue[2]) {
                 tms.adc.g_deviceTemperature = (double)tms.adc.g_rawAdcValue[2] * Max_Device_Temperature / Adc_Resolution;
                 sprintf(tms.msg,"DT = %5.2f\r\n", tms.adc.g_deviceTemperature);
                 UART2_Write_Text(tms.msg);
                 tms.adc.g_rawAdcValue[2] = tms.adc.g_oldRawAdcValue[2];
              }
              
              if(tms.adc.g_peltierVoltage <= Minimum_Peltier_Voltage) {
              
              }
              
              for(tms.i = 0; tms.i < 8; tms.i++) {
                  sprintf(tms.msg,"TC%u = %5.2f\r\n",tms.i, readMax31855(tms.i + 1));
                  UART2_Write_Text(tms.msg);
              }
         }
         else {
         
         }
         
         if(g_deviceSleeping == 0) {
            //BAUDCON1.WUE = 1;
            //BAUDCON2.WUE = 1;
            
            g_deviceSleeping = 1;
            //asm sleep
         }
    }
}

or like this ? See smaller image.


Both methods not working. There is a naming difference in Nexperia and other datasheets of 74HC138's E1, E2 and E3 pins.


Edit:

The E1, E2 and E3 pin numbers of 74HC138 differ in Nexperia datasheet and in Proteus model.
 

Attachments

  • TMS-MB-SIM-v1.2.PDF
    55.7 KB · Views: 57
  • TMS-v1.2-SS1.png
    TMS-v1.2-SS1.png
    67.8 KB · Views: 66
  • TMS-v1.2-SS2.png
    TMS-v1.2-SS2.png
    8.4 KB · Views: 69
Last edited:

Hi,

U19, pin41 is the "!SS" signal (look at the PICxx pin description)

Again: No, you don´t need pullups at the !CSx signals

Your schematic with U17 only is correct.

For sure your software should take care about the now LOW-active signal.

Klaus
 
Okay so I need a pullup on PIC18F pin 41 that is E1 signal connection ? That's all I need on hardware ? Changes have to be made in code ?

Please check this video.

https://www.youtube.com/watch?reload=9&v=1UKsOYXAO8E

There is pin name difference in Proteus model and Nexperia datasheet of 74HC138.

https://assets.nexperia.com/documents/data-sheet/74HC_HCT138.pdf

I can see SCK, SO, and CS (EN1) signals on the scope and there is some data on SO line but readings are always 0.00.

I didn't changed anything in code or circuit. Circuit remains same as that in post #74

Edit:

Problem was with sprintf() call that is the variable tms.i was char type and format specifier used was "%u". I changed it int type and "%d" and I started getting TCx values but values are not correct.

Code:
typedef struct {
    DEVICE_CONFIGURATION_TYPE deviceConfig;
    ADC_TYPE adc;
    UART1_TYPE uart1;
    UART2_TYPE uart2;
    int i;
    char msg[23];
    unsigned long temp[8];
    double temperature[8];
}TMS_TYPE;

- - - Updated - - -

Should I subtract ambient temperature which is 25 deg C in simulation from TCx readings to get exact temperature ?

Code:
double readMax31855(char channel) {
    char i = 0;
    signed long result = 0;
    double centigrade = 0.0;
    
    MUX_E1 = Low;
    
    if((channel >= 1) && (channel <= 8)) {
        channel = channel - 1;
        
        MUX_A = channel.B0;
        MUX_B = channel.B1;
        MUX_C = channel.B2;
        MUX_E1 = High;
        Delay_us(10);
    }
    

    for(i = 0; i < 32; i++) {
        SCLK = High;
        Delay_us(10);
        result <<= 1;
        if(SO)result |= 1;
        SCLK = Low;
        Delay_us(10);
    }
    
    MUX_E1 = Low;
    
    if(result & 0x80000000) {
        // Negative value, drop the lower 18 bits and explicitly extend sign bits.
        result = 0xFFFFC000 | ((result >> 18) & 0x00003FFFF);
    }
    else {
        // Positive value, just drop the lower 18 bits.
        result >>= 18;
    }

    centigrade = (double)result;

    return (centigrade * 0.25) - 25.0;
}
 

Attachments

  • TMS-v1.2-SS4.png
    TMS-v1.2-SS4.png
    275.6 KB · Views: 66
Last edited:

To be honest, I'm not sure what MUX_E1 is supposed to do. There is no need to disable all the CS signals, only to enable the one being used before the clocking starts.
There is a bug in the code - look closely at the timing diagrams (figure 1 and figure 2) in the MAX31855 data sheet, the data is available on the rising edge of the first clock after CS goes low. To be able to do that, SCK has to be low before CS goes low but. SCK is left in the low state after reading the data but the very first time a device is read, it's state is not defined.

I would advise:
Code:
SCK = 0;
Delay_us(1);  // only 100nS is actually needed.
result = 0;
for (i = 0; i < 32; i++)
{
SCK = 1;
Delay_us(1);
result << 1;
if (SO == 1) result |= 1;
else result &= 0xFFFE;
SCK = 0;
Delay_us(1);
}

I have not tried the code and I do not have a copy of Proteus but but seems more reasonable. I added the "else result &= 0xFFFE;" because I'm not sure what compiler you are using (MikroC ?) and it may not guarantee shifting zero in to bit0 during shift left instruction.

Brian.
 
@ betwixt

I am using mikroC.

Your code works but still I have to subtract ambient temperature reading from MAX31855 (TCx) readings to get correct readings. In Proteus MAX31855's ambient temperature is set to 25 deg C and if I subtract that value from MAX31855's centigrade reading then I get correct readings.
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top