|
|
View previous topic :: View next topic |
Author |
Message |
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
Stalling or locking up |
Posted: Sat Oct 04, 2008 11:34 am |
|
|
Greetings,
This is a continuation to the issues I've been encountering with my clock project.
What might cause a code to stall or lock up?
I have one 16F628A thats working fine, and doing exactly what its supposed to.
If I take the same code and write it to another 16F628A, the left digit displays only the A segment, and sometimes Pinb4 will also light up the colons.
It can be immediate, or take up to 3-4 minutes for it to occur.
Its almost like the code has stalled or locked up on power up.
Is there a way to check a pic to determine if it has failed?
Is there a way to stop the code from executing immediately on power up? sort of like a delayed start or soft start method to allow the circuit to energize first?
Just tossing out ideas
Suggstions?
Cheers
Steve
Code: | //========================================
//== COLON's not working correctly, should be off when Temp is displaying
//== COLON's should blink or pace with the seconds timer
#ignore_warnings 216 //Remove this at final compile
#include <16F628A.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOMCLR, NOLVP, NOCPD //628A
#use delay(clock=4000000, restart_wdt)
#include <ds1820.c>
#define RTC_SDA PIN_A2
#define RTC_SCL PIN_A3
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)
BYTE CONST MAP1[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
BYTE CONST MAP2[10]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF};
BYTE buff[DS1820_SCRATCH_BUFFER_SIZE];
BYTE sensor;
BYTE n;
BYTE temp;
BYTE temp_dec;
BYTE sec,min,hour;
BYTE fs_flag;
BYTE RES;
BYTE D_SHIFT;
BYTE Map_Choice;
BYTE ZERO;
#define DEC PIN_B1
#define INC PIN_B2
#define EXP_OUT_CLOCK PIN_B3
#define COLON PIN_B4
#define EXP_OUT_DO PIN_B5
#define EXP_OUT_CLEAR PIN_B6
#define EXP_OUT_LATCH PIN_B7
//========================================
// initial DS1307
//========================================
void init_DS1307()
{
output_float(RTC_SCL);
output_float(RTC_SDA);
}
//========================================
// write data one byte to DS1307
//========================================
void write_DS1307(byte address, BYTE data)
{
short int status;
i2c_start();
i2c_write(0xd0);
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
status=i2c_write(0xd0);
while(status==1)
{
i2c_start();
status=i2c_write(0xd0);
}
}
//========================================
// read data one byte from DS1307
//========================================
BYTE read_DS1307(byte address)
{
BYTE data;
i2c_start();
i2c_write(0xd0);
i2c_write(address);
i2c_start();
i2c_write(0xd1);
data=i2c_read(0);
i2c_stop();
return(data);
}
//=================================
// WRITE DATA TO 6B595
//=================================
void write_expanded_outputs(BYTE D)
{
BYTE i;
for(i=1;i<=8;++i)
{ // Clock out bits from the eo array
if ((D & 0x80)==0)
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
D=D<<1;
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
}
}
//=================================
// show temperature
//=================================
void show_temp()
{
signed int16 Temp16;
int1 TempIsPos;
int8 sensor;
int8 n;
int8 count;
output_high(COLON);
for (count=0;count<8;count++) // blink temperature 8 times
{
output_low(EXP_OUT_LATCH);
sensor=0; // DS1820 CONNECT TO PIN A0
init_ds1820(sensor);
write_ds1820_one_byte(0xcc, sensor); // skip ROM
write_ds1820_one_byte(0x44, sensor); // perform temperature conversion
while (read_ds1820_one_byte(sensor)==0xff); // wait for conversion complete
init_ds1820(sensor);
write_ds1820_one_byte(0xcc, sensor); // skip ROM
write_ds1820_one_byte(0xbe, sensor); // read the result
for (n=0; n<DS1820_SCRATCH_BUFFER_SIZE; n++) // read 9 bytes but, use only one byte
{
buff[n]=read_ds1820_one_byte(sensor); // read DS1820
}
Temp16 = make16(buff[1], buff[0]);
if (Temp16 > 0)
{
TempIsPos = TRUE;
Map_Choice = MAP1[RES]; // use normal
ZERO=0x00;
}
else
{
TempIsPos = FALSE;
Temp16 = -Temp16; // Make absolute value
Map_Choice = MAP2[RES]; // show the neg sign
ZERO=0xBF;
}
temp = Temp16 >> 4;
temp_dec = ((Temp16 & 0x0F) * 10) / 16;
// Display data
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
D_SHIFT=(0xD8); // Show 0xD8=°C, 0xF1=°F, 0xBF=-0 seg, 0x80=.
write_expanded_outputs(D_SHIFT);
D_SHIFT = MAP2[ temp_dec ]; // Show fraction
write_expanded_outputs(D_SHIFT);
RES = temp%10; // Show 1's
D_SHIFT = MAP1[RES];
write_expanded_outputs(D_SHIFT);
RES=temp/10; // Show 10's
if (RES==0)
D_SHIFT=ZERO;
else
D_SHIFT=Map_Choice;
write_expanded_outputs(D_SHIFT);
output_high(EXP_OUT_LATCH);
delay_ms(500);
output_low(EXP_OUT_LATCH);
for (n=1;n<=4;n++)
{
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
}
output_high(EXP_OUT_LATCH);
delay_ms(500);
}
}
//=================================
// show time 1
//=================================
void show_time1()
{
byte m;
output_low(EXP_OUT_LATCH);
output_low(COLON); //high keeps them on when all other commented out
min=read_ds1307(1);
hour=read_ds1307(2);
m=min & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(min);
m=min & 0x07;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
m=hour & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(hour);
m=hour & 0x03;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
output_high(EXP_OUT_LATCH);
swap(min);
swap(hour);
}
//=================================
// check switch
//=================================
void check_sw()
{
byte j;
if (fs_flag!=0)
{
if (!input(INC))
{
if (fs_flag==1)
{
min=read_ds1307(1);
min++;
j=min & 0x0F;
if (j>=0x0A) min=min+0x06;
if (min>=0x60) min=0;
write_ds1307(1,min);
}
else
{
hour=read_ds1307(2);
hour++;
j=hour & 0x0F;
if (j>=0x0A) hour=hour+0x06;
if (hour>=0x24) hour=0;
write_ds1307(2,hour);
}
show_time1();
}
if (!input(DEC))
{
if (fs_flag==1)
{
min=read_ds1307(1);
if (min!=0)
{
min--;
j=min & 0x0F;
if (j>=0x0A) min=min-0x06;
}
else min=0x59;
write_ds1307(1,min);
}
else
{
hour=read_ds1307(2);
if (hour!=0)
{
hour--;
j=hour & 0x0F;
if (j>=0x0A) hour=hour-0x06;
}
else hour=0x23;
write_ds1307(2,hour);
}
show_time1();
}
}
}
//=================================
// show time
//=================================
void show_time(byte fs)
{
byte m;
output_low(EXP_OUT_LATCH);
output_low(COLON);
min=read_ds1307(1);
hour=read_ds1307(2);
m=min & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(min);
m=min & 0x07;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
m=hour & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(hour);
m=hour & 0x03;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
output_high(EXP_OUT_LATCH);
swap(min);
swap(hour);
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
//delay_ms(500);
if (fs==0)
{
output_high(COLON);
//delay_ms(500);
}
else
{
if (fs==1)
{
output_high(COLON);
output_low(EXP_OUT_LATCH);
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
m=hour & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(hour);
m=hour & 0x03;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
output_high(EXP_OUT_LATCH);
//delay_ms(500);
}
else
{
output_high(COLON);
output_low(EXP_OUT_LATCH);
m=min & 0x0F;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
swap(min);
m=min & 0x07;
D_SHIFT=MAP1[m];
write_expanded_outputs(D_SHIFT);
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
D_SHIFT=0x00;
write_expanded_outputs(D_SHIFT);
output_high(EXP_OUT_LATCH);
//delay_ms(500);
}
}
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
delay_ms(100);
check_sw();
}
#int_EXT
void EXT_isr()
{
fs_flag++;
if (fs_flag>=3) fs_flag=0;
delay_ms(100);
}
//=====================================
// main program start here
//=====================================
void main(void)
{
byte u;
delay_ms(100);
port_b_pullups(true);
output_low(EXP_OUT_CLEAR);
delay_us(10); //was 10
output_high(EXP_OUT_CLEAR);
init_ds1307();
u=read_ds1307(0);
sec=u & 0x7F;// enable RTC
write_ds1307(0,sec); // set second to 00 and enable clock(bit7=0)
output_low(EXP_OUT_CLOCK);
fs_flag=0;
ext_int_edge(H_TO_L); // init interrupt triggering for button press
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(true)
{
disable_interrupts(INT_EXT);
if (fs_flag==0)
{
show_temp();
}
enable_interrupts(INT_EXT);
for (u=0;u<20;u++)
{
show_time(fs_flag);
}
}
} //end of main program
|
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
Re: Stalling or locking up |
Posted: Sat Oct 04, 2008 2:26 pm |
|
|
I have not crawled extensively through your code however I suggest the following:
Remove the delay_ms(100) from the interrupt handler EXT_isr(). If you do need a delay for some reason in the handler then code your own delay routine for the interrupt handler.
Sometimes developers forget to initialize variables before using them. In which case code execcution depends on the random contents of RAM at power up - these random vales will change between PIC. Two solutions, one is to instruct the compiler to force all uninitialized variables to be set to zero (this way the code should then behave the same for all PICs). The other solution is to insure you have initialized the variables.
From a hardware perspective, check you have used a pullup resistor on the SDI input to the PIC and the external interrupt input pin. If either pullup is missing it could also explain the symptom you are seeing.
If you are testing the your hardware without a battery for the RTC then this could also be a problem. Install a battery for the RTC. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Sat Oct 04, 2008 10:09 pm |
|
|
Thanks for the help Andrew.
Pull-ups have always been in place.
Removed the delay in the #int_ext routine, and so far no lock ups show on 3 of the 4 pics in question.. the 4th may just be a bad chip.
Still trying to figure out why the COLON is not functioning correctly, I've commented them all out and just started to bring them back in one at at time but most will not respond. May still be a bad chip, but it slow poking for now.
I can make them all output_high but in most cases the colons will not light up, although running a blinky routine on the same pin works fine. |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Sun Oct 05, 2008 7:15 am |
|
|
If I comment out ALL the Code: | output_high(COLON); |
and Pin_B4 defined as COLON will stay high and the LED's on it will remain lit.
If I return only 1 command for COLON to the routine, it matters not if the output is high or low, the LED's on B4 remain off.
I've tried several different combinations of Code: | output_high(COLON); | and
I dont understand why no output commands result in a high state for pin B4 with LED's on and any injection into the code for either state on Pin B4 results only in a low state with LED's off.
The only other function I can see with regards to B4 is in the routine where all Code: | port_b_pullups(true); |
Do I set the state of B4 in the variables and #defines section or is there another solution?
Cheers |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 05, 2008 8:49 am |
|
|
Quote: |
I don't understand why no output commands result in a high state for pin
B4 with LED's on |
Describe the circuit on Pin B4, in detail. Include a list of connections
with the pin numbers and component values.
Post the part numbers of any devices that you have connected to Pin B4. |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Sun Oct 05, 2008 9:55 am |
|
|
Pin_B4 connects to a 1K resistor which is connected to a 2N3904 base pin.
2N3904 Collector connects to a 12VDC source.
2N3904 Emitter connects to 2 standard red LED's 2.2v 20ma in series.
The LED's connect to a 180hm resistor which is in turn connected to ground.
The image below is the original circuit in use with only the BC557 and load resistor value changed.
On the following image, trace IC1 pin 10 which is the B4 output.
Replace the BC557 for the 2N3904 and the 1K resistor to a 180 Ohm between the LED's and ground.
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 05, 2008 12:51 pm |
|
|
Post a very small test program that shows the problem. |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 05, 2008 3:03 pm |
|
|
Also, you don't give details for the supply. What smoothing is on it?. What are the resistor values used for the LED segments?.
Best Wishes |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Sun Oct 05, 2008 4:46 pm |
|
|
PCM
A normal blinky code works fine on it.
Its the code as posted above that causing the problems.
Ttelmah
The smoothing is 12vdc through a 0.1uf and 100uf/16v before the 7805 and a 0.1uf after.
Led segments use 220ohm resistors
The led's on Pin B4 are as previously posted. 1KOhm from B4 to 2N3904 base pin, Collector is 12vdc, Emitter has the leds tied to ground with a 180ohm resistor.
The B4 circuit works fine with a Blinky code written to the chip. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 05, 2008 11:06 pm |
|
|
We don't want to look at a lot of code. There are almost certainly large
amounts of code in your program that can be cut, without affecting the
ability to demonstrate the "colon" problem.
You need to cut out some code, and then test it. See if it still shows the
problem. If so, cut out some more code. Keep doing that until you
have 50 lines or less. (But it still shows the problem). Then post it. |
|
|
Ttelmah Guest
|
|
Posted: Mon Oct 06, 2008 3:24 am |
|
|
I presume the 0.1uF on the circuit, really is adjacent to the PIC, and the other you mention, is close to the regulator?. 78xx regulators can have a tendency to oscillate, if there is not a capacitor really close to their output pins. The PIC itself also likes decoupling close to the chip.
A a 'general thing, I'd program the pins you are _not_ using (1, 2, 3, 17, 18), as outputs. Just output a value on each, so they are driven, rather than floating. Having inputs left floating, can always lead to problems, and extra power consumption.
As PCM says, you can reduce large lumps of the code, to find where the problem is. I'd start by removing the clock functions, and temperature functions, then just (for example), counting on the display, with the : being updated every tenth count).
I'd add 'delay_cycles(1)', between raising and lowering the output clock. Depending on the capacitances present, there might be a problem here.
Best Wishes |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Mon Oct 06, 2008 1:20 pm |
|
|
Thanks again
I'll peel back the codes until I get just the basics needed to show the colon issue as suggested.
I'll draw up a circuit showing the power input and post at the same time.
Cheers
Steve |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Mon Oct 06, 2008 2:53 pm |
|
|
By removing the Temperature code and working strictly on the time, I was able to correct the colon blink routine.
Bringing back in the Temperature routine, it was a simple switch of the remaining two output_ commands to make it dance the way I wanted.
I did discover in this process that 2 of the 4 pic's I was using did not function on pin_B4. A subsequent test with a blinky routine confirmed the 2 pics.
Outside of using a blinky routine for every output pin on the pic, is there a routine or other way to quickly check if the pic is functional?
Thanks again PCM and Ttelmah. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Mon Oct 06, 2008 4:18 pm |
|
|
You transistor driver schematic is probably at fault. Assuming the LEDs have a forward volt drop of 1.7 volts each and the transistor has a 0.7v vbe, then you need to apply in excess of 4.1V at the base of the transistor to start turning on. Your transistor driver is acting as a current limiter, as the voltage thru the emitter resistor increases, the voltage at the emitter rises so unless your input voltage rises on the base, your transistor will turn off.
One of more of the LEDs should have been connected between the collector and the +12volt rail. If you did not intend the transistor to be in a current limiting configuration then the emitter resistor should also have been on the collector side.
I suspect if you short out one of the LEDs it will start working. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Aurbo
Joined: 07 Apr 2008 Posts: 49
|
|
Posted: Sat Oct 11, 2008 10:09 am |
|
|
So far everything is working, Thanks to all that offered help to this noob.
I would like to blank or initialize the circuit each time its powered up,
All digits are cleared and display Zero for a second.
All file registers are cleared so everything starts with on a clean slate.
Would anyone have an example of this so I can try to break things again. and maybe learn something new in the process.
Cheers
Steve |
|
|
|
|
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
|