| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				| loop problem :( |  
				|  Posted: Thu Jan 08, 2009 5:21 pm |   |  
				| 
 |  
				| Hi guys I'm having problem with something that to you might be very simple, I'm using the pickit2 with the ccs compiler and I just wanted to know how can I jump from one loop to the other. I created this simple program but it won't let me. The compiler gives me the error because it won't jump unless the loop I want to go is on top, I hope this makes sense to you. Thank you. 
  	  | Code: |  	  | #include <16F887.h>             // header file for the PIC16F887 // includes built-in functions and constants
 // for arguments/returns.
 #FUSES NOWDT
 #FUSES NOMCLR
 #FUSES NOCPD
 #FUSES NOBROWNOUT
 #FUSES XT
 
 #use delay(clock=4000000)
 #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
 /////////////////////////////////////////////////////////////////////////////////
 
 
 void firstloop()
 {
 while(1){
 output_d(0xf0);
 if (getc()=='2')secondloop();
 }
 }
 
 
 void secondloop()
 {
 while(1){
 output_d(0x0f);
 if (getc()=='1')firstloop();
 }
 }
 
 
 void main()
 {
 
 while(true)
 {
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for first loop\r");
 printf("Press 2 for second loop\r");
 if (getc()=='1')firstloop();
 if (getc()=='2')secondloop();
 
 }
 
 }
 | 
 |  | 
	
		|  | 
	
		| treitmey 
 
 
 Joined: 23 Jan 2004
 Posts: 1094
 Location: Appleton,WI   USA
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 5:33 pm |   |  
				| 
 |  
				| you just need a prototype to show what the function looks like. But then you have recursive problem.
 try something more like this
 
  	  | Code: |  	  | #include <16F887.h>             // header file for the PIC16F887 // includes built-in functions and constants
 // for arguments/returns.
 #FUSES NOWDT
 #FUSES NOMCLR
 #FUSES NOCPD
 #FUSES NOBROWNOUT
 #FUSES XT
 
 #use delay(clock=4000000)
 #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
 //prototypes//
 void firstloop();
 void secondloop();
 //funtions
 void firstloop()
 {
 output_d(0xf0);
 }
 
 
 void secondloop()
 {
 output_d(0x0f);
 }
 
 //main//
 void main()
 {
 int8 getc_val;
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for first loop\r");
 printf("Press 2 for second loop\r");
 
 while(true)
 {
 getc_val=getc();
 if (getc_val=='1')firstloop();
 if (getc_val=='2')secondloop();
 
 }
 
 }
 | 
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 5:36 pm |   |  
				| 
 |  
				| You can't do recursion. That's what you're attempting to do.  You'll get this error message:
 
  	  | Quote: |  	  | *** Error 69 "pcm_test.c" Line 58(0,1): Recursion not permitted  [firstloop] | 
 |  | 
	
		|  | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 5:41 pm |   |  
				| 
 |  
				| THANK YOU SO MUCH!!!!!!!!!!!!!!!!!!!!! IT WORKS!!!!!!!!!!!!!!!!!!! |  | 
	
		|  | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 9:07 pm |   |  
				| 
 |  
				| it worked but is not what I was trying to do but thanx...this what I'm trying to do, I have a robot that I need it to work in remote and autonomous mode, so when I send a command it has to stay in the remote loop with all the features, and when I hit another command it has to stay in the autonomous mode with diferent features, thats why I'm trying to do 2 diferent loops. make sence?? |  | 
	
		|  | 
	
		| RLScott 
 
 
 Joined: 10 Jul 2007
 Posts: 465
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 10:13 pm |   |  
				| 
 |  
				|  	  | IceMetal wrote: |  	  | ...when I send a command it has to stay in the remote loop with all the features, and when I hit another command it has to stay in the autonomous mode with diferent features, thats why I'm trying to do 2 diferent loops. make sense?? | 
 
 Yes, but don't use getc() because it is blocking.  Use kbhit() to check for a new command without blocking.  If you want to use a function for loop 1 and another function for loop 2, then just have those functions return whenever kbhit() is true.  Then let the main command dispatcher loop in main decide which loop to call based on a reading of getc(), which you can do without blocking after kbhit() returns true.
 _________________
 Robert Scott
 Real-Time Specialties
 Embedded Systems Consulting
 |  | 
	
		|  | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Jan 08, 2009 10:16 pm |   |  
				| 
 |  
				| but how do I go to the loop that is at the bottom when I'm on the top loop? cuz when I'm trying to do that I get an error |  | 
	
		|  | 
	
		| FvM 
 
 
 Joined: 27 Aug 2008
 Posts: 2337
 Location: Germany
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 12:18 am |   |  
				| 
 |  
				| If you advance from the present very simple example to a real application, you most likely notice, that there are more things to do than stay in mutual exclusive loops representing different machine states. 
 To my opinion, it's more suitable to have a variable representing the different states, perform conditional code depending on the variable value, e. g. in a switch construct, and change the variable value to transit to another state. The technique is called finite state machine (FSM). In contrast to your loop example, you can divide the total system state into several substates, each representec by a FSM.
 
 If this sounds too complex for your application, keep your intial loop example, place all loops in one function block and transit by C goto statements. This works without causing recursion issues. As a basic disadvantage, you can't perform other actions at the main program level while staying in the loop.
 |  | 
	
		|  | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 2:09 am |   |  
				| 
 |  
				| well this is what I'm trying to do I mean I will replace the printf with output commands but just to give you an idea why I want to stay in the same loop, 
 
  	  | Code: |  	  | #include <16F887.h>             // header file for the PIC16F887 // includes built-in functions and constants
 // for arguments/returns.
 #FUSES NOWDT
 #FUSES NOMCLR
 #FUSES NOCPD
 #FUSES NOBROWNOUT
 #FUSES XT
 
 #use delay(clock=4000000)
 #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
 /////////////////////////////////////////////////////////////////////////////////
 
 //remote loop
 void remote()
 {
 while(1){
 if (getc()=='4')printf("go foward\r");
 if (getc()=='5')printf("go left\r");
 if (getc()=='6')printf("go right\r");
 if (getc()=='2')autonomous();
 }
 }
 
 //autonomous loop
 void autonomous()
 {
 while(1){
 printf("go foward\r");
 while(Input(PIN_A1))printf("go left\r");
 while(Input(PIN_A2))printf("go right\r");
 if (getc()=='1')remote();
 }
 }
 
 //main//
 void main()
 {
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 
 while(true)
 {
 if (getc()=='1')remote();
 if (getc()=='2')autonomous();
 
 }
 
 }
 | 
 |  | 
	
		|  | 
	
		| Wayne_ 
 
 
 Joined: 10 Oct 2007
 Posts: 681
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 3:53 am |   |  
				| 
 |  
				| I can't believe FvM sugested using goto to fix your problem! 
 You have 2 options, The first requires very little change to the way your are doing it but will limit you to only the 2 loops. And is basically a really silly way to do it.
 
 The break instruction will exit a while loop!
 
 
  	  | Code: |  	  | //remote loop
 void remote()
 {
 while(1){
 if (getc()=='4')printf("go foward\r");
 if (getc()=='5')printf("go left\r");
 if (getc()=='6')printf("go right\r");
 if (getc()=='2')break;
 }
 }
 
 //autonomous loop
 void autonomous()
 {
 while(1){
 printf("go foward\r");
 while(Input(PIN_A1))printf("go left\r");
 while(Input(PIN_A2))printf("go right\r");
 if (getc()=='1')break;
 }
 }
 
 //main//
 void main()
 {
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 
 while(true)
 {
 if (getc()=='1') {
 while(true) {
 remote();
 autonomous();
 }
 if (getc()=='2') {
 while(true) {
 autonomous();
 remote();
 }
 }
 }
 
 | 
 
 I was just going to try and show you the second way but before I do that there are really big problems with your code. As pointed out, by using getc you code will stop and wait for a keypress before continuing, it may appear to be working ok but you should have noticed that you need to send  the same value several times for it to perform the correct action!
 Also by fixing this you will simplify your code:-
 
 
  	  | Code: |  	  | 
 
 //remote loop
 void remote(int key)
 {
 if (key=='4')printf("go foward\r");
 if (key=='5')printf("go left\r");
 if (key=='6')printf("go right\r");
 }
 
 //autonomous loop
 void autonomous()
 {
 printf("go foward\r");
 while(Input(PIN_A1))printf("go left\r");
 while(Input(PIN_A2))printf("go right\r");
 }
 
 //main//
 void main()
 {
 int mode = 0
 int key;
 
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 
 while(true)
 {
 if (kbhit())  // If a key has been pressed
 key = getc();  // Save the key
 else
 key = 0;
 
 if (key == '1')
 mode = 1;
 else if (key == '2')
 mode = 2;
 
 if (mode==1)remote(key);
 if (mode==2)autonomous();
 
 }
 
 }
 
 | 
 
 This will make it work the same way where you have to hold a key down to make it perform that action continously, but if you want it to continue the same action even if you let go of the key then just remove the
 
 else
 key = 0;
 
 lines.
 |  | 
	
		|  | 
	
		| IceMetal 
 
 
 Joined: 20 Nov 2008
 Posts: 79
 Location: white Plains, NY
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 12:35 pm |   |  
				| 
 |  
				| thank you so much Wayne that really helped me alot!!!!!!!!!!!!!!!!!!!! |  | 
	
		|  | 
	
		| FvM 
 
 
 Joined: 27 Aug 2008
 Posts: 2337
 Location: Germany
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 12:45 pm |   |  
				| 
 |  
				|  	  | Quote: |  	  | I can't believe FvM sugested using goto to fix your problem! | 
 Believe it or not! Basically, I mentioned why staying in a loop most likely isn't a solution for a real application. But if it would be, goto is a suitable solution, you can use a lot of others too. It's legal C code.
 
 
  	  | Code: |  	  | void main() {
 char c;
 printf("Welcome:,\n\r");
 printf(" \n\r");
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 
 while(true)
 {
 c=getc();
 if (c =='1')
 while(1){
 remote:
 c=getc();
 if (c =='4')printf("go foward\r");
 if (c =='5')printf("go left\r");
 if (c =='6')printf("go right\r");
 if (c =='2') goto  autonomous;
 }
 if (c =='2')
 while(1){
 autonomous:
 printf("go foward\r");
 while(Input(PIN_A1))printf("go left\r");
 while(Input(PIN_A2))printf("go right\r");
 if (kbhit() && getc()=='1') goto remote;
 }
 }
 }
 | 
 |  | 
	
		|  | 
	
		| andrewg 
 
 
 Joined: 17 Aug 2005
 Posts: 316
 Location: Perth, Western Australia
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Fri Jan 09, 2009 9:29 pm |   |  
				| 
 |  
				| Gotos really should be avoided, particularly for such a simple loop. My first take was: but I didn't like the duplicate code for left/right/forwards. So then I came up with: 	  | Code: |  	  | void main() {
 int1 remote = TRUE;
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 for (;;)
 {
 if (kbhit())
 {
 switch (getc())
 {
 case '1':
 remote = TRUE;
 break;
 case '2':
 remote = FALSE;
 break;
 case '4':
 if (remote) printf("go forward\r");
 break;
 case '5':
 if (remote) printf("go left\r");
 break;
 case '6':
 if (remote) printf("go right\r");
 break;
 }
 }
 if (!remote)
 {
 printf("go forward\r");
 if (input(PIN_A1)) printf("go left\r");
 if (input(PIN_A2)) printf("go right\r");
 }
 }
 }
 | 
 All the previous code examples suffer from the potential problem in autonomous mode where if the inputs stay high, you'll never be able to switch to remote mode. 	  | Code: |  	  | void main() {
 int1 remote = TRUE;
 printf("Press 1 for remote\r");
 printf("Press 2 for autonomous\r");
 for (;;)
 {
 int8 c = 0;
 if (kbhit())
 {
 c = getc();
 if (!remote && c >= '4') c = 0; // no remote control in autonomous mode
 }
 else if (!remote)
 {
 c = '4';
 if (input(PIN_A1)) c = '5';
 if (input(PIN_A2)) c = '6';
 }
 
 switch (c)
 {
 case '1':
 remote = TRUE;
 break;
 case '2':
 remote = FALSE;
 break;
 case '4':
 printf("go forward\r");
 break;
 case '5':
 printf("go left\r");
 break;
 case '6':
 printf("go right\r");
 break;
 }
 }
 }
 | 
 _________________
 Andrew
 |  | 
	
		|  | 
	
		| FvM 
 
 
 Joined: 27 Aug 2008
 Posts: 2337
 Location: Germany
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Jan 10, 2009 3:43 am |   |  
				| 
 |  
				| Any arguments? 	  | Quote: |  	  | Gotos really should be avoided | 
 
 To my opinion,you really should avoid to code state machines in an unstructurized way. For this reason, any of the suggested  examples is effectively bad coding style (at least from an embedded application point of view). My goto version simply emphasizes this bad style instead of hiding it. You immediately see, that you're stuck in a loop, as apparently intended.
 
 To find a better coding style, you should analyze the application purpose first and define a meaningful behaviour. The original post indicates, that this hasn't been done yet. It's generally difficult to apply improvements to an inconsistent code.
 |  | 
	
		|  | 
	
		| andrewg 
 
 
 Joined: 17 Aug 2005
 Posts: 316
 Location: Perth, Western Australia
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Sat Jan 10, 2009 7:59 pm |   |  
				| 
 |  
				| Speaking of coding style, something I meant to mention before relates to the first two code samples provided by IceMetal: 
 http://www.ccsinfo.com/forum/viewtopic.php?p=109099#109099
 http://www.ccsinfo.com/forum/viewtopic.php?p=109115#109115
 
 They are just plain wrong under all circumstances, from embedded systems to supercomputers. The problem is that firstloop() and secondloop() are always calling each other and never returning. This will eventually cause any computer to run out of memory and crash. Embedded systems will just get there first due to less memory.
  _________________
 Andrew
 |  | 
	
		|  | 
	
		|  |