|
|
View previous topic :: View next topic |
Author |
Message |
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
How to use a delay function? |
Posted: Thu Nov 15, 2007 11:32 am |
|
|
I need to to use a delay function in the following code to make the data that is being sent over the rs232 receive correctly. Problem is that everytime i repeat the while loop i have to sent some value but the delay function of 20ms affects the response time of my pic so much that it shows on the lcd. Is there a better way to delay a certain if function without it delaying all other functions?? A simple thing like blinking an LED every second would basically let the pic only run 1 cycle every second??
Code: | if(weapon > 190){
output_high(pin_B2);
PutCC1000(PREAMBLE);
PutCC1000(0X0B);
PutCC1000(0X0B);
PutCC1000(0X0B);
putc('Y');
delay_ms(20);
putc(10);
delay_ms(20);
putc(weapon);
delay_ms(20);
putc('Z');
delay_ms(20);
} |
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Nov 15, 2007 12:46 pm |
|
|
Quote: |
Is there a better way to delay a certain if function without it delaying all other functions??
|
The key is to use any built-in timer to handle the equal-time scheduled events.
Something like this, not tested.
Code: |
setup_timerx(......);// Set Timerx for an interrupt every 20ms
if(weapon > 190){
output_high(pin_B2);
PutCC1000(PREAMBLE);
PutCC1000(0X0B);
PutCC1000(0X0B);
PutCC1000(0X0B);
putc('Y');
set_timerx(0);
enable_interrupt(INT_TIMERx);
enable_interrupt(GLOBAL);
timed_putc = 1;
}
#INT_TIMERx
void timed_events()
{
switch(timed_putc)
{ case 1: putc(10); timed_putc = 2; break;
case 2: putc(weapon); timed_putc = 3; break;
case 3: putc('Z'); timed_putc = 4; break;
case 4: disable_interrupt(INT_TIMERx); break;
}
}
|
Humberto
Last edited by Humberto on Thu Nov 15, 2007 1:07 pm; edited 1 time in total |
|
|
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
|
Posted: Thu Nov 15, 2007 1:02 pm |
|
|
Thanks. What will happen then if i have two functions during the cycle that calls the interupt? If the interupt is still busy being executed while i call it again via another if statement, will the system not become unstable??
I have 3 analogs and sometimes i need to send 3 different values, depending on where the 3 analogs is during one cycle as well as what the value is in that cycle?? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Nov 15, 2007 1:14 pm |
|
|
While an interrupt is handled, by no way it will be affected by another interruptds
until it finished.
The aproach I gave you should work in background, it is according your first answer.
I do not see your whole code and how do you handle the events, but if you are dealing
with multiple events, you could use different timers.
To consider all the posibilities we will know more details of your project.
Humberto |
|
|
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
|
Posted: Thu Nov 15, 2007 1:53 pm |
|
|
Here is the part where i have the different functions. I don't want to post the whole code as it is a university subject where all the students will use my code. I have this pic comunicating with a cc1000 as well as a LCD.
Code: |
//////////////////////////////////////////////////////////////////
while(1){
///////////////////////////////weapon//////////////////////////
delay_ms(50);
set_adc_channel(3);
delay_us(20);
weapon = read_adc();
if(weapon > 190){
output_high(pin_B2);
PutCC1000(PREAMBLE);
PutCC1000(0X0B);
PutCC1000(0X0B);
PutCC1000(0X0B);
putc('Y');
delay_ms(20);
putc(10);
delay_ms(20);
putc(weapon);
delay_ms(20);
putc('Z');
delay_ms(20);
}
else
if(weapon <85){
output_high(pin_B4);
PutCC1000(PREAMBLE);
PutCC1000(0X0C);
PutCC1000(0X0C);
PutCC1000(0X00);
putc('Y');
delay_ms(20);
putc(20);
delay_ms(20);
putc(weapon);
delay_ms(20);
putc('Z');
delay_ms(20);
}
else
if(weapon < 191 && weapon > 84){
output_low(pin_B4);
output_low(pin_B2);
}
////////////////////////////////////left and right//////////////////////////////////////////////
set_adc_channel(2);
delay_us(20);
value1 = read_adc();
if(value1 > 170 ){
output_high(pin_A4);
output_low(pin_B5);
output_low(pin_B3);
PutCC1000(PREAMBLE);
PutCC1000(0x1A);
PutCC1000(0x1A);
PutCC1000(value1);
putc('Y');
delay_ms(20);
putc(30);
delay_ms(20);
putc(value1);
delay_ms(20);
putc('Z');
delay_ms(20);
}
else
if((value1 > 150 && value1 < 171)||(value1 > 69 && value1 < 91 )){
output_low(pin_A4);
output_low(pin_B5);
output_low(pin_B3);
PutCC1000(PREAMBLE);
PutCC1000(0x1B);
PutCC1000(0x1B);
PutCC1000(0x00);
}
else
if(value1 < 70 ){
output_high(pin_A5);
output_low(pin_B5);
output_low(pin_B3);
PutCC1000(PREAMBLE);
PutCC1000(0x1C);
PutCC1000(0x1C);
PutCC1000(0x00);
putc('Y');
delay_ms(20);
putc(40);
delay_ms(20);
putc(value1);
delay_ms(20);
putc('Z');
delay_ms(20);
}
//////////////////////////////forward reverse/////////////////////////////////////////////////
if(value1 > 90 && value1 <151){
output_low(pin_A4);
output_low(pin_A5);
set_adc_channel(1);
delay_us(20);
value = read_adc();
if(value > 0 && value < 116 ) {
output_low(pin_B5);
output_high(pin_B3);
PutCC1000(PREAMBLE);
PutCC1000(0x3A);
PutCC1000(0x3A);
PutCC1000(140-value);
putc('Y');
delay_ms(20);
putc(50);
delay_ms(20);
putc(140-value);
delay_ms(20);
putc('Z');
delay_ms(20);
}
else
if(value > 115 && value < 161 ) {
output_low(pin_B5);
output_low(pin_B3);
}
else
if(value > 160) {
output_low(pin_B3);
output_high(pin_B5);
PutCC1000(PREAMBLE);
PutCC1000(0x3B);
PutCC1000(0x3B);
PutCC1000(value-131);
putc('Y');
delay_ms(20);
putc(60);
delay_ms(20);
putc(value-131);
delay_ms(20);
putc('Z');
delay_ms(20);
}
}
if((weapon<191&&weapon>84)&&(value1 > 90 && value1 <151)&&(value > 115 && value < 161)){
PutCC1000(PREAMBLE);
PutCC1000(0xBB);
PutCC1000(0xBB);
PutCC1000(0x00);
putc('Y');
delay_ms(20);
putc(111);
delay_ms(20);
putc(weapon);
delay_ms(20);
putc('Z');
delay_ms(20); |
Here is the part of the code for the pic connected to the LCD,.
Code: | #include <16F886.H>
#fuses INTRC,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NODEBUG
#use delay(clock = 4000000)
#use RS232 (STREAM=serial,BAUD=19200,XMIT=PIN_C6,RCV=PIN_C7)
#include "flex_lcd.c"
int pack_offset = 0;
int packet_in[4] = {0,0,0,0};
int speed = 0;
int dir = 0;
int x = 0;
int weapon=0;
#int_rda //serial interupt service routine
void serial_isr() {
byte rcv_char;
int x;
if (kbhit()) { //char ready on uart to come in
rcv_char = getc();
if(rcv_char == 'Y'){
pack_offset = 0;
}
packet_in[pack_offset] = rcv_char;
if( (rcv_char == 'Z') && (packet_in[0] == 'Y') ){
dir = packet_in[1];
speed = packet_in[2];
//delay_ms(500);
}
pack_offset++;
} //kbhit
}
//==========================
void main()
{
int x;
enable_interrupts(INT_RDA); // Enable Serial Reception Interrupt
enable_interrupts(GLOBAL); //Enable interupts global
lcd_init(); // Always call this first.
lcd_gotoxy(1,1);
lcd_putc("\f PLEASE WAIT!!");
lcd_gotoxy(1,2);
lcd_putc(" INITIALISING!");
delay_ms(1000);
while(1){
delay_ms(200);
if(dir==10){
lcd_gotoxy(1,2);
lcd_putc("LID MOVING DOWN ");
// printf(LCD_PUTC, "%u",speed);
}
if(dir==20)
{
lcd_gotoxy(1,2);
lcd_putc("LID MOVING UP ");
}
if(dir==111)
{
lcd_gotoxy(1,1);
lcd_putc("MOTION INACTIVE ");
lcd_gotoxy(1,2);
lcd_putc("WEAPONS INACTIVE ");
}
if(dir==30)
{
lcd_gotoxy(1,1);
lcd_putc("TURN LEFT ");
lcd_gotoxy(13,1);
x=((speed-170)*2)+15;
printf(LCD_PUTC, "%u",x);
lcd_gotoxy(16,1);
lcd_putc("% ");
}
else
if(dir==40)
{
lcd_gotoxy(1,1);
lcd_putc("TURN RIGHT ");
lcd_gotoxy(13,1);
x= (75-speed)*3;
printf(LCD_PUTC, "%u",x);
lcd_gotoxy(16,1);
lcd_putc("% ");
}
else
if(dir==50)
{
lcd_gotoxy(1,1);
lcd_putc("REVERSE ");
lcd_gotoxy(13,1);
x= speed+10;
printf(LCD_PUTC, "%u",x);
lcd_gotoxy(16,1);
lcd_putc("% ");
}
else
if(dir==60)
{
lcd_gotoxy(1,1);
lcd_putc("FORWARD ");
lcd_gotoxy(13,1);
x= speed;
printf(LCD_PUTC, "%u",x);
lcd_gotoxy(16,1);
lcd_putc("% ");
| }
Here is a part of the code for the recieving end of the cc1000. I still have to implement the rs232 for this side to display the recieved RF comands.
Code: | while(1){
/////////////////////////////////////////////////////////////////
set_adc_channel(0);
delay_us(20);
signal = read_adc();
if(signal>30){
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a3);
output_low(pin_a4);
output_low(pin_a5);
output_low(pin_b4);
output_low(pin_b5);
set_pwm1_duty(0);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_B);
delay_ms(500);
output_high(pin_B3);
delay_ms(500);
output_low(pin_B3);
}
else
if(signal<31){
if (CCRX_BUFFCOUNT >= 4) { // As 4 bytes ontvang is
temp = GETCC1000();
if(temp == PREAMBLE){
pay1 = GETCC1000();
crc = GETCC1000();
speed = GETCC1000();
if(pay1!=crc){
delay_ms(5);
output_low(pin_b3);
output_high(pin_b3);
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a3);
output_low(pin_a4);
output_low(pin_a5);
output_low(pin_b4);
output_low(pin_b5);
set_pwm1_duty(0);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_B);
}
else{
output_high(pin_b3);
if (pay1==0xBB){
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a3);
output_low(pin_a4);
output_low(pin_a5);
output_low(pin_b4);
output_low(pin_b5);
set_pwm1_duty(0);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_B);
output_high(pin_B3);
}
//////////////////weapon///////////////////////////////////////////////////
if(pay1 == 0x0B)
{
output_high(pin_A5);
output_low(pin_b4);
output_high(pin_b5);
}
else
if(pay1 == 0x0C){
output_low(pin_A5);
output_high(pin_b4);
output_high(pin_b5);
}
//////////////////////////////////right/////////////////////////////////////////////////////////
if(pay1 == 0x1A){
output_low(pin_a1);
delay_ms(5);
output_high(pin_a2);
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);
output_high(pin_a3);
output_high(pin_a4);
}
else
if(pay1 == 0x1B){
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a3);
output_low(pin_a4);
set_pwm1_duty(0);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_B);
}
else
if(pay1 == 0x1C){
output_low(pin_a3);
output_low(p1c);
output_high(pin_a2);
output_high(pin_a4);
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_B);
output_high(pin_a1);
}
//////////////////////////////forward/////////////////////////////////////////
if(pay1 == 0x3A){
output_low(pin_a3);
output_low(pin_a1);
delay_ms(5);
output_high(pin_a2);
output_high(pin_a4);
output_high(pin_b2);
output_high(pin_b5);
set_pwm1_duty(speed);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);
}
else
if(pay1 == 0x3B){
output_low(pin_b2);
output_low(pin_b5);
delay_ms(5);
set_pwm1_duty(speed);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);
output_high(pin_a2);
output_high(pin_a4);
output_high(pin_a1);
output_high(pin_a3);
}
}
}//einde van crc
}//einde van if(ccrx_bufcount)
}//einde van seinsterkte toets
}//einde van hoof WHILE |
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Nov 15, 2007 9:49 pm |
|
|
Your code looks quite twisted and for sure you have multiple and overlapped results in each loop.
It seems like you need to update the positions in 3 servos simultaneously according to
some environment variables. I propose you to think the problem in the opposite way.
First, make a main loop with an interrupt every 7ms. Then you will need to assign 3 tasks
to update parameters for each servo spaced by 21ms. You can get it using the same
timer, in this way you will "visit" the same servo every 21ms, hence you will have enough
time to collect the environment inputs data and update the corresponding parameters.
Humberto |
|
|
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
|
Posted: Fri Nov 16, 2007 3:09 am |
|
|
Thanks.
Will you please explain your advice a bit more. I am reading the value of a analog for a forward-reverse action.
Code: | if(value1 > 90 && value1 <151){
output_low(pin_A4);
output_low(pin_A5);
set_adc_channel(1);
delay_us(20);
value = read_adc();
if(value > 0 && value < 116 ) {
output_low(pin_B5);
output_high(pin_B3);
PutCC1000(PREAMBLE);
PutCC1000(0x3A);
PutCC1000(0x3A);
PutCC1000(140-value);
putc('Y');
delay_ms(20);
putc(50);
delay_ms(20);
putc(140-value);
delay_ms(20);
putc('Z');
delay_ms(20);
}
else
if(value > 115 && value < 161 ) {
output_low(pin_B5);
output_low(pin_B3);
}
else
if(value > 160) {
output_low(pin_B3);
output_high(pin_B5);
PutCC1000(PREAMBLE);
PutCC1000(0x3B);
PutCC1000(0x3B);
PutCC1000(value-131);
putc('Y');
delay_ms(20);
putc(60);
delay_ms(20);
putc(value-131);
delay_ms(20);
putc('Z');
delay_ms(20);
} |
As well as for left and right. However the forward reverse is only read if the left right analog is in the middle.
The third one i am reading is another analog that indicates if the lid of the car is moving up or down.
I am fairly new to pics and very new at using interupts so if you can please just give me some details as to what you propose. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Fri Nov 16, 2007 10:14 am |
|
|
1) Set an internal timer to kick every 6.4ms. to handle the servos.
Code: |
setup_timer_2(T2_DIV_BY_16,124,16); // (6.4ms @20Mhz)
|
2) Use a variable to handle the LCD display.
Code: |
int update_display;
|
3) In the servo handler routine, make an incremental task handler (like the switch()
function I showed you previously)
Code: |
#int_TIMER2
void servos_handler_isr(void)
{
update_display++;
switch(task_handler)
{
case 1: update_servo_1();
task_handler++;
break;
case 2: update_servo_2();
task_handler++;
break;
case 3: update_servo_3();
task_handler=1;
break;
}
}
|
4) In the main(), take out the 200ms delay and do all the evaluations (if(...) of the
involved variables (value, value1 and weapon) and set the data field of the payloads
accordingly.
5) In main() the display should be easily updated using the same timer.
Code: |
if(update_display== 60) // this is TRUE every ~400ms
{show_display();
update_display=0;}
|
These are the steps I would do just in case, of course it would be incomplete but we
do not have enough info of your project. You will see that the program is always running,
with any waiting loops while all the timed events are triggered in background.
I just tried to show you how to do it in a structured and more controllable way,
writting code that will enable you to test it step by step.
Humberto |
|
|
|
|
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
|