|
|
View previous topic :: View next topic |
Author |
Message |
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
Mitigating a fault... |
Posted: Sun Oct 23, 2016 12:43 am |
|
|
Hi there,
I am using the SHT21 driver code (https://www.ccsinfo.com/forum/viewtopic.php?t=45751) to sample guess what... a sht21
However, if the sensor is disconnected or fail it will hang the whole PIC.
I suspect that the driver is waiting for a ACK from the SLAVE thus is stuck in an infinite waiting loop.
What would be the best option to detect and isolate the fault?
I've seen some software i2c routine with a timeout but I need to stay with hardware.
I tried a simple code like this:
Code: |
if (faultflag == 0){sht21_both(temperature,humidity);}
if (temperature == -46.85){faultflag=1;} //known value when it fail to read the SHT21 and to skip the next reading
|
For some reason I get the first reading (-46.85) over serial then hang maybe on the second attempt...
Using a 24FJ128GA010 with PCWHD 5.063.
EDIT:
Whole code for clarity
Code: |
#include <24FJ128GA010.h>
#FUSES XT,PR_PLL,NOPROTECT,NOJTAG,NOWDT,NOOSCIO
#use delay(clock=32M)
#use rs232(baud=9600,UART1,ERRORS)
#use i2c(Master,fast,i2c1)
#include "sht21.c"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int1 sendflag = 1;
int1 faultflag =0;
float temperature,humidity;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#INT_TIMER2
void timer2_isr(void)
{
sendflag = 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void sendpacket(){
if (faultflag == 0){printf("#:%3.2f,%3.2f*\n\r",temperature,humidity);}
else {printf("I2C Sensor fault\n\r");}
output_toggle(PIN_G15);
}
void main ()
{
sht21_init();
delay_ms(1000);
setup_timer2(TMR_INTERNAL | TMR_DIV_BY_256 | TMR_32_BIT, 625000); //10 sec trigger
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while (true)
{
if (sendflag){
if (faultflag == 0){sht21_both(temperature,humidity);}
if (temperature == -46.85){faultflag=1;}
sendpacket();
sendflag = 0;
}
}
}
|
_________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Sun Oct 23, 2016 1:15 am |
|
|
This is just down to testing the ACK.
Look at PCM_Programmers I2C bus scanning program (in the code library). Note how this works - it tests the ACK bit from the write to see if a device is present.
What you do is in each routine, on the first write to the device address, check for the ACK, before proceeding to the rest of the I/O.
So something like:
Code: |
I2C_start();
if (I2C_write(sht21)==0)
{
//chip is there
i2c_write(softreset);
i2c_stop();
delay_ms(15);
}
|
If you do the same for every transaction, then it won't hang (normally...).
Now ideally, you probably want to set a flag to say there is the error, so your other code knows the value is not being updated, and also this can still hang, if the device is disconnected 'mid transaction'. Handling this is down to using a timeout if it is felt to be likely. |
|
|
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Sun Oct 23, 2016 1:24 am |
|
|
Ttelmah wrote: | This is just down to testing the ACK.
Look at PCM_Programmers I2C bus scanning program (in the code library). Note how this works - it tests the ACK bit from the write to see if a device is present.
What you do is in each routine, on the first write to the device address, check for the ACK, before proceeding to the rest of the I/O.
So something like:
Code: |
I2C_start();
if (I2C_write(sht21)==0)
{
//chip is there
i2c_write(softreset);
i2c_stop();
delay_ms(15);
}
|
If you do the same for every transaction, then it won't hang (normally...).
Now ideally, you probably want to set a flag to say there is the error, so your other code knows the value is not being updated, and also this can still hang, if the device is disconnected 'mid transaction'. Handling this is down to using a timeout if it is felt to be likely. |
Well thanks for your reply... it was something very dumb...
I'm ashamed to post my finding
Code: | setup_timer2(TMR_INTERNAL | TMR_DIV_BY_256 | TMR_32_BIT, 625000); //10 sec trigger |
Obviously NOT 10 sec trigger like PCDWiz timer code snip had calculated.
Swapped for the regular 16 bit timer code to see
Code: | setup_timer2(TMR_INTERNAL | TMR_DIV_BY_256 , 62500); // 1 sec trigger |
The i2c routine respond when disconnected...it just display the -46.85 values like it should when the sht21 is not present.
The hanging was just the Timer2 32 bit mode not working .
Sorry for this thread ... it 3 AM I need sleep!!! _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Sun Oct 23, 2016 1:40 am |
|
|
We have all had that...
Normally it'd only 'hang' if the driver waits for a reply, or if the bus gets shorted low. I didn't bother to check if either of these could apply to this driver.
However testing for ACK, is a great way of knowing the chip actually is present. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|