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 support@ccsinfo.com

why my servo motor did not work

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



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

why my servo motor did not work
PostPosted: Fri Apr 11, 2008 9:07 pm     Reply with quote

I'm using pic16F877A. i only have one input (temperature sensor - LM335) and one output (servo motor). i tried to control servo motor direct without sensor, its work. but when i tried to control servo with input (temperature sensor) my servo did not work. my printf appear (normal/suam/sedang/panas) but my servo did not move. why? anyone can help me? here is my source code...

Code:
#include <16F877A.H>
#device ADC=10 //10bit Analog digital conveter
#use delay (clock=20000000) // 20MHz
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP


#define SERVO1 PIN_b0 // motor RC servo //pin 33
#define led_hijau PIN_b6 // pin 39
#define led_merah PIN_b7 //pin 40
int i;          // looping

//////////////////////////////////////////////////////////
////////////////////// ADC ///////////////////////////////
//////////////////////////////////////////////////////////

#BYTE ADCON0 = 0x1F
int16 ch1_result,ch2_result;
float volt;
#int_AD
AD_isr()
{
   if (((ADCON0 & 0x38) >>3) == 1)
   {
      ch1_result = read_adc();
      set_adc_channel(2);
   }

   else
   {
      ch2_result=read_adc();
      set_adc_channel(1);
   }
   ADCON0 |= 0x4;
}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////// function() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

void suam()
{
      for (i=0;i<30;i++)                            //60 deg
      {
         output_high(SERVO1);
         delay_us(1900);
         output_low(SERVO1);
         delay_us(18100);
      }


}


void sedang()                                       //30 deg
{
      for (i=0;i<30;i++)
      {
         output_high(SERVO1);
         delay_us(1600);
         output_low(SERVO1);
         delay_us(18400);
      }

}

void panas()
{
      for (i=0;i<30;i++)             // 0 deg
      {
        output_high(SERVO1);
        delay_us(1300);
        output_low(SERVO1);
        delay_us(18700);
      }

}


void normal()
{
     for (i=0;i<30;i++)              // 90 deg
     {
         output_high(SERVO1);
         delay_us(2200);
         output_low(SERVO1);
         delay_us(17800);
     }

}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////////// main() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////



void main()
{



   setup_adc_ports(ALL_ANALOG);     // SETTING ADC CHANNEL
   setup_adc(ADC_CLOCK_DIV_32);
   enable_interrupts(INT_AD);
   enable_interrupts(global);
   set_adc_channel(1);
   ADCON0 |= 0x4;
   set_tris_b(0x00);


while(1)
     {
         volt=(float)((ch1_result)/1023.0*5); // ADC pin A1
         printf("\f Volt: %3.2f",volt);   // current volt
         delay_ms(500);



        if ((volt > 3.0)&&(volt<3.3))
            {
               printf("\f suam");
               output_high(led_merah);
               suam();

            }

            else if ((volt > 3.3)&&(volt<3.5))
            {
               printf("\f sedang");
               output_high(led_merah);
               sedang();
            }

            else if ((volt > 3.5))
            {
               printf("\f panas");
               output_high(led_merah);
               panas();
            }

            else
            {
               printf("\f normal");
               normal();
               output_high(led_hijau);
           }
     }
}


////////////////////////////////////////////////////
///////////////////////////////////////////////////
////////////////////////////////////////////////////



////////////////////////////////////////////////////
///////////////////test servo without sensor///////////////////////
////////////////////////////////////////////////////
/*
main()
{

while(1)

{

for (i=0;i<30;i++)
                 {
                     output_high(SERVO1);
                     delay_us(1700);
                     output_low(SERVO1);
                     delay_us(18300);
                 }

 for (i=0;i<30;i++)
                 {
                     output_high(SERVO1);
                     delay_us(2200);
                     output_low(SERVO1);
                     delay_us(17800);
                 }

for (i=0;i<30;i++)             // 180 deg
                 {
                    output_high(SERVO1);
                    delay_us(2400);
                    output_low(SERVO1);
                    delay_us(17600);
                 }

for (i=0;i<30;i++)             // 90 deg
                 {
                    output_high(SERVO1);
                    delay_us(1500);
                    output_low(SERVO1);
                    delay_us(18500);
                 }

      }
}
*/
////////////////////////////////////////////////////
////////////////test servo without sensor//////////////////////
////////////////////////////////////////////////////


/*
main()
{

while(1)

{

suam();
sedang();
panas();
normal();

}
}
*/
////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////

Guest








PostPosted: Sat Apr 12, 2008 2:32 am     Reply with quote

Your problem, is using INT_AD.
You trigger the ADC to convert. Then 96 instruction times latter, the ADC finishes it's conversion, and triggers the ADC interrupt. It takes about 30 instruction times to arrive in the interrupt. You use perhaps another dozen instructions performing the test to find which channel to read. Then call the 'read_adc' function, _which used without a value, triggers another conversion_. 96 instruction times latter, this value is available, and is read (another perhaps 8 instructions). You then trigger another ADC conversion to start, and exit the interrupt (about another 28 instructions tl you get back into your main code). About 74 instructions latter, the whole ADC cycle starts again. So your processor, ends up spending about 74 instructions in the 'main' code, and about 176 instructions in the interrupt handler. Time delays are _only_ done in 'main' time, so an instruction like 'delay_us(1900)', will take about 6400uSec to execute. Hence your servo timing goes completely screwed, and the servo stops working.
The serial code keeps working, because the timing for this is done in hardware.
Do a search here on INT_ADC. You will find a lot of posts by me, on why this really should _not_ be used. Even if you used the 'read_adc(ADC_READ_ONLY)' call, which is the correct way to read the ADC inside an interrupt loop, you would still spend nearly as lng, calling the interrupt, reading the value, and returning, as the ADC conversion itself takes.
For your code, it'll be simpler, and work better, to just use read_adc, to get the value, select the next channel to read, perform the servo update, and loop, without using the interrupt at all.

Best Wishes
fxfifi



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 11:37 am     Reply with quote

thank you for your co-operation. so what should i do with my source code?
fxfifi



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 9:08 pm     Reply with quote

please somebody help me...i got stuck with my source code..i don't know what modification i should do with my coding. i don't know how to setting adc/interupt.
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 9:49 pm     Reply with quote

do you have to use an interrupt for the adc? why not just read it in the main routine.

do you have to use a floating point number why not use an integer like 55 represents 5.5V and 30 represent 3.0V coz as far as i understand floating point numbers take a lot longer deal with.
fxfifi



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 10:34 pm     Reply with quote

so how the coding you suggest?
fxfifi



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

still cannot work
PostPosted: Sun Apr 13, 2008 12:56 am     Reply with quote

ok.. i have change a little bit of my program.. i dont understand how to read adc without interrupt..


my summary project is like this... i want to control water valve using RC servo motor.. i have set if temperature between certain volt the motor will turn.. there are 4 condition normal, minimum, warm and hot..

when i run my project, the temperature rise and the LED change but the motor still not move..

i have search and ask my friend.. but still cannot work.. so i ask the expert in this forum.. hehe~ can any one help me adjust my program.. i am new in programming.. thanks







Code:
Code:


#include <16F877A.H>
#device ADC=10 //10bit Analog digital conveter
#use delay (clock=20000000) // 20MHz
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP


#define SERVO1 PIN_b0 // motor RC servo //pin 33
#define led_green PIN_b6 // pin 39
#define led_red PIN_b4 //pin 37
#define led_pink PIN_b7  //pin 40
#define led_blue PIN_b5  //pin 38
int i; // looping

//////////////////////////////////////////////////////////
////////////////////// ADC ///////////////////////////////
//////////////////////////////////////////////////////////

#BYTE ADCON0 = 0x1F
int16 ch1_result,ch2_result;
float volt;
#int_ad
AD_isr()
{
   
   {
      ch1_result = read_adc();
     set_adc_channel(1);
   }
   
   ADCON0 |= 0x4;

}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////// function() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

void warm()
{
   printf("\f temperature warm");
   delay_ms(100);
      for (i=0;i<30;i++)                //0 deg
      {
         output_low(led_blue);
         output_low(led_pink);
         output_low(led_red);
         output_high(led_green;

         output_high(SERVO1);
         delay_us(1900);
         output_low(SERVO1);
         delay_us(18100);
      }


}


void minimun()                           //30 deg
{
   printf("\f temperature minimum");
   delay_ms(100);
      for (i=0;i<30;i++)
      {
         output_low(led_green);
         output_low(led_pink);
         output_low(led_red);
         output_high(led_blue);

         output_high(SERVO1);
         delay_us(1600);
         output_low(SERVO1);
         delay_us(18400);
      }

}

void hot()
{
   printf("\f stemperature hot");
   delay_ms(100);
      for (i=0;i<30;i++)             // 60 deg
      {
        output_low(led_blue);
        output_low(led_pink);
        output_low(led_green);
        output_high(led_red);

        output_high(SERVO1);
        delay_us(1300);
        output_low(SERVO1);
        delay_us(18700);
      }

}


void normal()
{
   printf("\f temperature normal ");
   delay_ms(100);
     for (i=0;i<30;i++)             // 90 deg
     {
         output_low(led_blue);
         output_low(led_red);
         output_low(led_green);
         output_high(led_pink);

         output_high(SERVO1);
         delay_us(2200);
         output_low(SERVO1);
         delay_us(17800);
     }

}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////////// main() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////



void main()
{



   setup_adc_ports(ALL_ANALOG);     // SETTING ADC CHANNEL
   setup_adc(ADC_CLOCK_DIV_32);
   enable_interrupts(INT_AD);
   enable_interrupts(global);
   set_adc_channel(1);
   ADCON0 |= 0x4;
   set_tris_b(0x00);



while(1)
     {
         volt=(float)((ch1_result)/1023.0*5); // ADC pin A1
         printf("\f Volt: %3.2f",volt);   // reading
         delay_ms(500);



        if ((volt > 3.0)&&(volt<3.3))
            {
               warm();
            }

        else if ((volt > 3.3)&&(volt<3.5))
            {
               minimum();
            }

        else if ((volt > 3.5))
            {

               hot();
            }

        else
            {
               normal();

            }
     }
}

[/code]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 1:36 am     Reply with quote

Quote:
i dont understand how to read adc without interrupt

http://www.ccsinfo.com/forum/viewtopic.php?p=86899&start=1
fxfifi



Joined: 11 Apr 2008
Posts: 6

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 1:54 am     Reply with quote

ok thanks... after trail n error.. my project wok!! thanks~~

code]

#include <16F877A.H>
#device ADC=10 //10bit Analog digital conveter
#use delay (clock=20000000) // 20MHz
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP


#define SERVO1 PIN_b0 // motor RC servo //pin 33
#define led_hijau PIN_b6 // pin 39
#define led_merah PIN_b4 //pin 37
#define led_pink PIN_b7 //pin 40
#define led_biru PIN_b5 //pin 38
int i; // looping

//////////////////////////////////////////////////////////
////////////////////// ADC ///////////////////////////////
//////////////////////////////////////////////////////////

#BYTE ADCON0 = 0x1F
int16 ch1_result;
float volt;


/////////////////////////////////////////////////////////////////////////////
////////////////////////////// function() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

void suam()
{
printf("\f suhu output suam sekarang");
delay_ms(100);
for (i=0;i<30;i++) //0 deg
{
output_low(led_biru);
output_low(led_pink);
output_low(led_merah);
output_high(led_hijau);

output_high(SERVO1);
delay_us(1900);
output_low(SERVO1);
delay_us(18100);
}


}


void sedang() //30 deg
{
printf("\f suhu output sedang sekarang");
delay_ms(100);
for (i=0;i<30;i++)
{
output_low(led_hijau);
output_low(led_pink);
output_low(led_merah);
output_high(led_biru);

output_high(SERVO1);
delay_us(1600);
output_low(SERVO1);
delay_us(18400);
}

}

void panas()
{
printf("\f suhu output panas sekarang");
delay_ms(100);
for (i=0;i<30;i++) // 60 deg
{
output_low(led_biru);
output_low(led_pink);
output_low(led_hijau);
output_high(led_merah);

output_high(SERVO1);
delay_us(1300);
output_low(SERVO1);
delay_us(18700);
}

}


void normal()
{
printf("\f suhu output normal sekarang");
delay_ms(100);
for (i=0;i<30;i++) // 90 deg
{
output_low(led_biru);
output_low(led_merah);
output_low(led_hijau);
output_high(led_pink);

output_high(SERVO1);
delay_us(2200);
output_low(SERVO1);
delay_us(17800);
}

}

/////////////////////////////////////////////////////////////////////////////
////////////////////////////////// main() ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////



void main()
{



setup_adc_ports(ALL_ANALOG); // SETTING ADC CHANNEL
setup_adc(ADC_CLOCK_DIV_32);




while(1)
{

set_adc_channel(1);
ch1_result = read_adc();
volt=(float)((ch1_result)/1023.0*5); // ADC pin A1
printf("\f Volt: %3.2f",volt); // BACAAN SEMASA
delay_ms(500);


if ((volt > 3.1)&&(volt<3.3))
{
suam();
}

else if ((volt > 3.3)&&(volt<3.5))
{
sedang();
}

else if ((volt > 3.5))
{

panas();
}

else
{
normal();

}
}

}
[/code]
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 2:08 am     Reply with quote

you can try this i just finished working on it. i think it should work.

Code:
#include <16F877A.H>
#device ADC=8 // can change to 10bit if you want to increase accuracy
#use delay (clock=20000000) // 20MHz
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial


#define SERVO1 PIN_b0 // motor RC servo //pin 33
#define led_green PIN_b6 // pin 39
#define led_red PIN_b4 //pin 37
#define led_pink PIN_b7  //pin 40
#define led_blue PIN_b5  //pin 38
int8 i; // looping

unsigned int8 Volt; // Stores adc value 0-255


void warm()
{
   printf("\f temperature warm");
      for (i=0;i<30;i++)                //0 deg
      {
         output_low(led_blue);
         output_low(led_pink);
         output_low(led_red);
         output_high(led_green);

         output_high(SERVO1);
         delay_us(1900);
         output_low(SERVO1);
         delay_ms(18);  // dont need to be exactly 200 Hz frequency only the high part is important as far as i know
      }
}


void minimum()                           //30 deg
{
   printf("\f temperature minimum");
      for (i=0;i<30;i++)
      {
         output_low(led_green);
         output_low(led_pink);
         output_low(led_red);
         output_high(led_blue);

         output_high(SERVO1);
         delay_us(1600);
         output_low(SERVO1);
         delay_ms(18);  // dont need to be exactly 200 Hz frequency only the high part is important as far as i know
      }
}

void hot()
{
   printf("\f temperature hot");
      for (i=0;i<30;i++)             // 60 deg
      {
        output_low(led_blue);
        output_low(led_pink);
        output_low(led_green);
        output_high(led_red);

        output_high(SERVO1);
        delay_us(1300);
        output_low(SERVO1);
        delay_ms(18);  // dont need to be exactly 200 Hz frequency only the high part is important as far as i know
      }
}


void normal()
{
   printf("\f temperature normal ");
     for (i=0;i<30;i++)             // 90 deg
     {
         output_low(led_blue);
         output_low(led_red);
         output_low(led_green);
         output_high(led_pink);

         output_high(SERVO1);
         delay_us(2200);
         output_low(SERVO1);
         delay_ms(18);  // dont need to be exactly 200 Hz frequency only the high part is important as far as i know
     }
}

void main()
{
   setup_adc( ADC_CLOCK_INTERNAL );
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

         set_adc_channel(1);  // set up so sensor is on pin a1
         delay_ms(15);
         
   while(1)
     {
      Delay_ms(1000); // delay so it only check temp every second.
                      // can put whatever sample rate you want here.
     
         Volt = read_adc();   //reads the adc result
                              // so will output int8 where 255 = 5V and so on assuming 5V supply
                              // actual voltage at sensor = 5V * (Volt/255)
                             
            printf("\f Volt int: %u",volt);   // reading 0 to 255 for voltage factor
           

        if ((volt > 153) && (volt < 168)) // int8 values for 3V and 3.3V
            {  warm();  }

        else if ((volt > 168) && (volt < 178)) // int8 values for 3.3V and 3.5V
            {  minimum();  }

        else if ((volt > 178)) //// int8 values for 3.5V
            {  hot();   }

        else
            {  normal();  }
     }
}
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