CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Question about creating delays inside of a while loop

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

Question about creating delays inside of a while loop
PostPosted: Thu May 15, 2008 8:57 am     Reply with quote

Hello,

I have written the code below. The purpose of this is to use is as a video source switcher between 2 video sources. The program will verify the position of the RC Transmitter stick or switch and it will switch a pin high or low in function of the stick position - by counting the lenght of the pulses.

There is also a failsafe which should prevent switching on it's own - it will switch only after 10 valid pulses in the required range are received.

The other failsafe I need to build in, is that in case of a complete signal loss after 2 or 4 seconds (value to be determined) it will switch back to the 1st video source. Now this is the part which is not working, and I do not understand why. At the moment once I switch the RC receiver off, it switches right away without any delay. I need a 2 to 4 seconds delay there, because the signal loss might be temporary and may come back in less then 2-4 seconds.

So here is the code:

Code:

#include "Vidsplit.h"

#define Signal    PIN_A4          //define pin for incoming signal
#define vidsig    PIN_A0          //define pin for outgoing signal
#define  High     1
#define  Low      0
#define  Middle   2
#define Status    char

int flag;
int16 count;
int8  sfty;
int16 time;

unsigned char oldpos;
unsigned char position;

Status Checksignal(unsigned char pos);

void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_comparator(NC_NC_NC_NC);
   Output_low(vidsig);                                      //clear the output port
   oldpos = Low;                                            //set starting position
   sfty = 0;                                                //initialize safety counter
   time = 0;                                                //initialize timer counter

While(true){

    position = Checksignal(position);                       //go and check the stick position
   
    if (Flag == 1) {
      Flag = 0;
      Output_low(vidsig);                                   //if the timer is at 4000 - we lost the tx signal
    }                                                       //for more than 4 seconds, it is time to make sure
                                                            //the channel 1 is active
    Else {                                                  //if the counter is less then 4000, then we are still safe
    if ( position || oldpos)                                //check if the position has changed compared to the previous state
    {
            oldpos = position;                              //if it did, make the oldposition equal to the newposition

       Switch (position) {                                  //switch based on the position
               Case Low:
                  Output_low(vidsig);
                  Delay_ms(50);
                  sfty = 0;
               Break;

               Case High:
                  Output_High(vidsig);
                  Delay_ms(50);
                  sfty = 0;
               Break;
               Case Middle:
                  Delay_ms(50);
               Break;


      }
    }
   }
}
}
Status CheckSignal(unsigned char pos) {
    count = 0;                                           // initialize the pulse counter
    time = 0;
    While (!input(Signal)) {                             // Wait for pin to come on
         time++;
         If (time > 2000) {
            flag = 1;
            Break;
         }
    }
    While (input(Signal)) {count++;}                     // Once the signal is high, count
    If (count > 80 && count < 220) {                     // Make sure you are dealing with a valid pulse
    sfty++;                                              // Increase safety counter
      If (sfty = 10) {                                    // we need 5 valid signals to switch - it will eliminate accidental switching
           sfty = 0;                                     // if it is 5, then clear the counter
           if (count <= 120) return(Low);                // If the count is under 120 then we are on the low end
           else if (count >= 180) return(High);          // If the count is over 180 then we are on the high end
           else return(Middle);                          // In case we are on the rudder stick the middle gets you nowhere.
      }
    }
}



and the h file:

Code:

#include <12F629.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BANDGAP_HIGH         
#use delay(clock=4000000)
//#use rs232(baud=9600,parity=N,xmit=PIN_A3,rcv=PIN_A2,bits=8)
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu May 15, 2008 9:35 am     Reply with quote

I didn't study your code very well but I did notice a few things.

Code:
position = Checksignal(position);
The variable 'position' is not initialised at startup, but...
Code:
Status CheckSignal(unsigned char pos) {
...you never use 'pos' anyway so it is best to get rid of this parameter.

Code:
If (sfty = 10) {
Change to '=='

Code:
if ( position || oldpos)    //check if the position has changed compared to the previous state
Change the '||' to '!='.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu May 15, 2008 9:47 am     Reply with quote

Thank you, these are great, I will correct these, however the problem is in the following portion which never gets executed:

Code:

    While (!input(Signal)) {                             // Wait for pin to come on
         time++;
         If (time > 2000) {
            flag = 1;
            Break;
         }
    }


here, instead of counting to 2000 it will break the loop right away.
mindstorm88



Joined: 06 Dec 2006
Posts: 102
Location: Montreal , Canada

View user's profile Send private message

PostPosted: Thu May 15, 2008 9:58 am     Reply with quote

Do you realise that at 4 mHz clock your 2000 count should last about 2000 uSec or 2 mS !!!!
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu May 15, 2008 10:03 am     Reply with quote

Quote:
here, instead of counting to 2000 it will break the loop right away.
Which means your A4 input pin is always high when you enter this function. What does the electronic schematic connected to this pin look like?

Add code for disabling the pull-up resistor on PIN A4. These should be disabled by default but it doesn't hurt to make this explicit.
Code:
port_a_pullups(0x00);   // Disable all weak pull up resistors


What is your compiler version number? (see top of the *.lst file)


Last edited by ckielstra on Thu May 15, 2008 10:34 am; edited 1 time in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu May 15, 2008 10:27 am     Reply with quote

Some more remarks:
- Variable Flag is not initialized at startup.

Code:
#define  High     1
#define  Low      0
#define  Middle   2
#define Status    char
This code is correct, but if you want to do it realy nice than you code it with an enumeration which was designed for this purpose. A good compiler will then do type checking for you.
Code:
enum Status {Low, Middle, High};


Code:
 While (input(Signal)) {count++;}
This is a very rough mechanism for time measurement. A new compiler version or change in clock frequency will break this code. Try something like:
Code:
  While (input(Signal))
  {
    count++;
    delay_us(200);
  }
Make sure the delay routine is relatively long compared to the loop overhead (about 8us at 4Mhz).

There is a possible program flow where the function CheckSignal() does not return a value. This is a bug and too bad the compiler does not warn you for this.


Last edited by ckielstra on Thu May 15, 2008 10:34 am; edited 1 time in total
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu May 15, 2008 10:32 am     Reply with quote

mindstorm88 wrote:
Do you realise that at 4 mHz clock your 2000 count should last about 2000 uSec or 2 mS !!!!


Thanks, I had it at 20000 and it did not make any difference. However furher down while the "signal is on" it counts properly. It brings me back the correct values, and it switches pretty nicely.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu May 15, 2008 10:35 am     Reply with quote

ckielstra wrote:
Quote:
here, instead of counting to 2000 it will break the loop right away.
Which means your A4 input pin is always high when you enter this function. What does the electronic schematic connected to this pin look like?

Add code for disabling the pull-up resistor on PIN A4.

What is your compiler version number? (see top of the *.lst file)


That might be the case, I have to verify that tonight. However the RC receivers signal is directly connected to this pin an I tested the signal coming out from the receiver with a scope - it goes low the moment the signal is lost - so it should bring the pin low as well, however I have to verify this.

I am not certain what the compiler version is, I have to check once i get home.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu May 15, 2008 10:45 am     Reply with quote

ckielstra wrote:
Some more remarks:
- Variable Flag is not initialized at startup.



that is the most likely problem of my code. I think this will solve it.

ckielstra wrote:

Code:
#define  High     1
#define  Low      0
#define  Middle   2
#define Status    char
This code is correct, but if you want to do it realy nice than you code it with an enumeration which was designed for this purpose. A good compiler will then do type checking for you.
Code:
enum Status {Low, Middle, High};



Well, I am not really a programmer, thanks for pointing that out, I will defintely look into changing that.

ckielstra wrote:

Code:
 While (input(Signal)) {count++;}
This is a very rough mechanism for time measurement. A new compiler version or change in clock frequency will break this code. Try something like:
Code:
  While (input(Signal))
  {
    count++;
    delay_us(200);
  }
Make sure the delay routine is relatively long compared to the loop overhead (about 8us at 4Mhz).



Well, thank you again, but I timed this such that it works for me. The pulses coming from the rc receiver should be between 1ms to 2ms. To get an accurate measurement and also keep the code simple enough I changed the clock settings in the h file, so for 1.5ms middle position to count 150, lower position 1ms to be a 100 count and the high position - 2ms to be a 200 count.

This is precise enough for my application. It is very unlikely I will port this to a different compiler version of a different clock setting.

Quote:

There is a possible program flow where the function CheckSignal() does not return a value. This is a bug and too bad the compiler does not warn you for this.


thank you.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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