|
|
View previous topic :: View next topic |
Author |
Message |
rodorico
Joined: 14 Nov 2010 Posts: 8
|
Unexpected Reboot at PIC 16F876, Why ? |
Posted: Sun Nov 14, 2010 2:17 pm |
|
|
Hi people, I have this problem and I don't know how to resolve it.
I'm executing this c code, and when I send some operations (*move (leftmove, forwardmove, rightmove, leftmovestop....)) at the rs232 from the PC to the PIC, normally when I do it faster (from the key PC), The PIC reboot, and I don't know why.
I attach my main function and the int_rda function:
Code: |
void main()
{
/* inicializacion de variables */
duty_wheel_left = duty_stop;
duty_wheel_right = duty_stop;
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
/* configuramos interrupciones del timer2 */
set_tris_b (0xF0); /* puerto b 0,1,2,3 out, others in */
//set_timer2 (0);
//set_timer0(0xFF);
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); /* configuramos el timer 0*/
setup_timer_2 (T2_DIV_BY_1, 0x63, 1); /* establece el timer2 para 10Khz */
enable_interrupts (INT_RDA); /* habilitamos interrupciones rs232 */
enable_interrupts (GLOBAL); /* habilitamos todas las interrupciones */
printf("WELCOME");
/* habilitamos interrupciones */
//enable_interrupts (INT_RB); /* habilitamos interrupciones en el puerto B */
//enable_interrupts (INT_TIMER0); /* habilitamos interrupciones del timer0 */
//enable_interrupts (INT_TIMER2); /* habilitamos interrupciones del timer2 */
/* inicializamos el valor de los pines */
output_high (PIN_B1);
output_high (PIN_B0);
output_low (PIN_B2);
high_b2 = false;
manual_move = true;
/* bucle infinito */
while (true) {
if (starts) {
read_tpa81(TPA81_ID);
disable_interrupts(GLOBAL);
printf("%C\n",setTermalScan);
printf("%U,%U,%U,%U,%U,%U,%U,%U,%U\n", t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9]);
enable_interrupts(GLOBAL);
delay_ms(termalScanPeriod);
}
}
}
#int_RDA
interrupt_RS232 () {
operation = getc();
printf("Operacion recibida: %C\n", operation);
// operation to move the robot forward
else if (operation == forwardMove) {
moving_forward =true;
next_duty_wheel_left = duty_forward_left;
next_duty_wheel_right = duty_forward_right;
}
// operation to move the robot to the backward
else if (operation == backwardMove) {
moving_backward =true;
next_duty_wheel_left = duty_backward_left;
next_duty_wheel_right = duty_backward_right;
}
// operation to move the robot to the left
else if (operation == leftMove) {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_forward_right;
}
// operation to move the robot to the right
else if (operation == rightMove) {
next_duty_wheel_left = duty_forward_left;
next_duty_wheel_right = duty_stop;
}
// operation to move the robot forward
else if (operation == forwardMoveStop) {
moving_forward =false;
if (moving_backward) {
next_duty_wheel_left = duty_backward_left;
next_duty_wheel_right = duty_backward_right;
}
else {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
}
}
// operation to move the robot to the backward
else if (operation == backwardMoveStop) {
moving_backward = false;
if (moving_forward) {
next_duty_wheel_left = duty_forward_left;
next_duty_wheel_right = duty_forward_right;
}
else {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
}
}
// operation to move the robot to the left
else if (operation == leftMoveStop) {
if (moving_forward) {
next_duty_wheel_left = duty_forward_left;
next_duty_wheel_right = duty_forward_right;
}
else if (moving_backward) {
next_duty_wheel_left = duty_backward_left;
next_duty_wheel_right = duty_backward_right;
}
else {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
}
}
// operation to move the robot to the right
else if (operation == rightMoveStop) {
if (moving_forward) {
next_duty_wheel_left = duty_forward_left;
next_duty_wheel_right = duty_forward_right;
}
else if (moving_backward) {
next_duty_wheel_left = duty_backward_left;
next_duty_wheel_right = duty_backward_right;
}
else {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
}
}
// operation to stop moving the robot
else if (operation == stopMove) {
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
}
// operation to kwon that the robot is alive
else if (operation == heartbeat) {
}
// operation to start the vigilance
else if (operation == start) {
set_timer2 (0);
set_timer0(0xFF);
enable_interrupts(INT_RB);
enable_interrupts(INT_TIMER2);
starts = true;
}
// operation to stop the vigilance
else if (operation == stop) {
disable_interrupts(INT_RB);
disable_interrupts(INT_TIMER0);
disable_interrupts(INT_TIMER2);
starts = false;
}
} |
Any Idea.... |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Sun Nov 14, 2010 2:34 pm |
|
|
My first guess is that you have noise on the PIC power pins when you do the move commands.
Does it reset if you have your motors disconnected?
What chip are you using?
What are your fuse settings?
Do you have capacitors across (all of) the PIC power pins?
How is MCLR terminated? |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1939 Location: Norman, OK
|
|
Posted: Sun Nov 14, 2010 3:49 pm |
|
|
Since you did not show all your code, one thing I see right off:
Code: | #int_RDA
interrupt_RS232 () {
operation = getc();
printf("Operacion recibida: %C\n", operation);
|
The printf in your interrupt routine can cause all
kinds of problems. You are using getc() to fetch one character then try to
PRINTF at least 19 characters immediately after. This will cause your
RS232 buffer to UART overflow and the PIC to hang. If you have the WDT
timer enabled you will get a reset. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Sun Nov 14, 2010 5:31 pm |
|
|
pmuldoon wrote: | My first guess is that you have noise on the PIC power pins when you do the move commands.
Does it reset if you have your motors disconnected? |
yes it happens with the motors disconnected
Quote: | What chip are you using? |
16f876
Quote: | What are your fuse settings? |
Code: |
#fuses XT,NOWDT, NOPROTECT, NOLVP, PUT, NOBROWNOUT
#use delay (clock = 4000000)
#use rs232 (baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use I2C(master, sda=PIN_C4, scl=PIN_C3)
|
Quote: | Do you have capacitors across (all of) the PIC power pins? |
No I don't have none capacitors.
Quote: | How is MCLR terminated? |
watch it here
http://www.x-robotics.com/images/PIC16f876_3basic.gif
Hi pmuldoon, I answer at your quote
Any Idea ? |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Sun Nov 14, 2010 5:40 pm |
|
|
dyeatman wrote: | Since you did not show all your code, one thing I see right off:
Code: | #int_RDA
interrupt_RS232 () {
operation = getc();
printf("Operacion recibida: %C\n", operation);
|
The printf in your interrupt routine can cause all
kinds of problems. You are using getc() to fetch one character then try to
PRINTF at least 19 characters immediately after. This will cause your
RS232 buffer to UART overflow and the PIC to hang. If you have the WDT
timer enabled you will get a reset. |
Hi dyeatman,
mm I have enabled the Timer0 interrupts but not the WDT.
And the reset is not occur always that I send that printf.
Anyway tomorrow I'll try without that printf.
The configuration I have for the timer0 no enabled the WDT ?
Code: |
#int_rb
interrupt_RB()
{
/** Interrupcion del sensor de movimiento **/
if (input(PIN_B6) && !timer_move_sensor) {
timer_move_sensor = true;
cicles_delay_move_sensor = number_cicles_delay_move_sensor;
enable_interrupts (INT_TIMER0);
if (high_b2) {
output_low(PIN_B2);
high_b2 = false;
}
else {
output_high(PIN_B2);
high_b2 = true;
}
printf("%C\n", setMoveAlarm);
}
/** Interrupciones de los sensores de luz del siguelineas **/
if (!input(PIN_B5) && !manual_move)
next_duty_wheel_left = duty_stop;
else if (input(PIN_B5) && !manual_move)
next_duty_wheel_left = duty_forward_left;
if (!input(PIN_B4) && !manual_move)
next_duty_wheel_right = duty_stop;
else if (input(PIN_B4) && !manual_move)
next_duty_wheel_right = duty_forward_right;
}
and the configuration for the timer0:
void main()
{
/* inicializacion de variables */
duty_wheel_left = duty_stop;
duty_wheel_right = duty_stop;
next_duty_wheel_left = duty_stop;
next_duty_wheel_right = duty_stop;
/* configuramos interrupciones del timer2 */
set_tris_b (0xF0); /* puerto b 0,1,2,3 out, others in */
set_timer0(0xFF);
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); /* configure timer0 to 16 ms */
|
Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Nov 14, 2010 9:18 pm |
|
|
It would be better if you posted a small, but complete test program that
shows the problem. You can probably cut out a large amount of your
code and still create a program that shows the problem. Try to do that.
Then post it. The program that you post should be compilable with no
errors. Test it before you post it. It must have the #include for the PIC,
and the #fuses, and the #use delay(), and all variable declarations, and
a main().
But remember, if you make the program very short, it will be easier for
us to see the problem. We don't want to look at a lot of code, if the
problem can be shown in just a few lines. |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Mon Nov 15, 2010 5:10 am |
|
|
PCM programmer wrote: | It would be better if you posted a small, but complete test program that
shows the problem. You can probably cut out a large amount of your
code and still create a program that shows the problem. Try to do that.
Then post it. The program that you post should be compilable with no
errors. Test it before you post it. It must have the #include for the PIC,
and the #fuses, and the #use delay(), and all variable declarations, and
a main().
But remember, if you make the program very short, it will be easier for
us to see the problem. We don't want to look at a lot of code, if the
problem can be shown in just a few lines. |
Ok i'll try to post a short test program to check. |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Mon Nov 15, 2010 3:53 pm |
|
|
Hi, I'm making some test and this is my conclusion, the problem is at the while(true) loop.
If I no put code inside it works fine, but if I insert code, the pic reboots.
This is the while loop
Code: |
/* loop */
while (true) {
if (starts) {
read_tpa81(TPA81_ID);
printf("%C\n",setTermalScan);
delay_ms(1);
printf("%U,%U,%U,%U,%U,%U,%U,%U,%U\n", t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9]);
enable_interrupts(GLOBAL);
delay_ms(termalScanPeriod);
}
}
|
and the read_tpa81
Code: | void read_tpa81( byte slaveID ) {
for ( i=0; i<10; i++) {
i2c_start();
i2c_write(slaveID);
i2c_write(i);
i2c_start();
i2c_write(slaveID+1);
t[i] = i2c_read(0);
i2c_stop ();
delay_ms(10);
}
} |
any Idea....
Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 15, 2010 4:05 pm |
|
|
I can't really do anything without a (short) complete test program
and the compiler version. |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Nov 16, 2010 3:11 am |
|
|
I agree with PCM programmer but as you are trying to track the problem down yourself, try commenting out individual lines in the while to see which one causes the reboot!
Also:-
printf("%U,%U,%U,%U,%U,%U,%U,%U,%U\n", t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9]);
I notice you are accessing your array starting at [1], arrays in C start at base 0 [0], but as you have not posted the variable definition I can not say if this is a problem!
Forget that, I see what you are doing, but still, you don't post ANY variable definitions! |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Thu Nov 18, 2010 10:44 am |
|
|
Here is a short program test,
I'm printing every x second 9 values from a thermal scan connected to the pic by I2c, and attached is all the code of the short program with all the variable declarations.
Code: |
#fuses XT,NOWDT, NOPROTECT, NOLVP, PUT, NOBROWNOUT
#use delay (clock = 4000000)
#use rs232 (baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use I2C(master, sda=PIN_C4, scl=PIN_C3)
/* PIN_B6 represents move sensor input */
/* PIN_B4 represents left line sensor */
/* PIN_B5 represents right line sensor */
/* PIN_B0 represents left wheel */
/* PIN_B1 represents right wheel */
boolean manual_move;
boolean starts = false;
boolean moving_forward = false;
boolean moving_backward = false;
boolean moving_left = false;
boolean moving_right = false;
char operation;
int i = 0;
byte t[10];
void read_tpa81( byte slaveID ) {
for ( i=0; i<10; i++) {
i2c_start();
i2c_write(slaveID);
i2c_write(i);
i2c_start();
i2c_write(slaveID+1);
t[i] = i2c_read(0);
i2c_stop ();
}
}
#int_RDA
interrupt_RS232 () {
operation = getc();
// operation to kwon that the robot is alive
if (operation == heartbeat) {
printf("%C\n", heartbeat);
}
// operation to start the vigilance
else if (operation == start) {
set_timer2 (0);
set_timer0(0xFF);
enable_interrupts(INT_TIMER2);
output_high (PIN_B1);
output_high (PIN_B0);
starts = true;
}
// operation to stop the vigilance
else if (operation == stop) {
disable_interrupts(INT_RB);
disable_interrupts(INT_TIMER0);
disable_interrupts(INT_TIMER2);
output_low (PIN_B1);
output_low (PIN_B0);
starts = false;
}
}
void main()
{
/* configuramos interrupciones del timer2 */
set_tris_b (0xF0); /* puerto b 0,1,2,3 out, others in */
enable_interrupts (INT_RDA); /* habilitamos interrupciones rs232 */
enable_interrupts (GLOBAL); /* habilitamos todas las interrupciones */
printf("WELCOME\n");
output_low (PIN_B1);
output_low (PIN_B0);
output_low (PIN_B2);
manual_move = true;
/* bucle infinito */
while (true) {
delay_ms(1000);
read_tpa81(TPA81_ID);
printf("%C\n",setTermalScan);
for (i = 1; i <10; i++){
if (i == 9)
printf("%U",t[i]);
else
printf("%U,",t[i]);
}
putc('\n');
}
}
|
When I send a lot of commands by rs232 to the robot, it reboots, printing again the WELCOME message. |
|
|
rodorico
Joined: 14 Nov 2010 Posts: 8
|
|
Posted: Fri Nov 19, 2010 8:45 am |
|
|
any idea guys |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Nov 19, 2010 9:10 am |
|
|
I don't know if this is the problem or not, but here's a couple of things I would do differently:
Don't enable/disable interrupts in the interrupt routine. Enable them in main() before your infinite loop and leave them enabled. SET or CLEAR a flag in your #int_RDA and use an if(FLAG) to determine whether to execute the code in your other interrupt routines.
Same thing with the printf. Don't printf inside the interrupt. Set a flag and put an if(FLAG)printf(...) in your main loop.
Just my thoughts, but hope it helps. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Fri Nov 19, 2010 9:10 am |
|
|
Add 'errors' to the use rs232(....) function.
Set 'flags' inside the ISR.
Remove all prints,etc. inside the isr.
In the main program loop, test the 'flags' and take the apporopriate action. |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Nov 19, 2010 9:13 am |
|
|
Ahh, the ERRORS gotcha!
I missed that completely. |
|
|
|
|
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
|