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

Analog Read and Motor Drive 18F2550 SOLVED

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



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

Analog Read and Motor Drive 18F2550 SOLVED
PostPosted: Fri Oct 07, 2016 4:40 am     Reply with quote

Hello

I try to analog read an optical encoder data, and drive motor according to that data. I tried these 2 codes and they are working. When i try to mix them, they don't. I think i am doing something wrong with the setup settings. Any ideas?

I use L293d motor drive and 18F2550.

Thanks and sorry for bad english.

My encoder code (this one works):
Code:

#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#device ADC=10
#use delay(clock=4000000)
#use fast_io(A)
#define encoder_data PIN_A0


unsigned int16 ADC_read()   //adc read function
   {
      unsigned int16 encoder_val=0;
      set_adc_channel(0);
      delay_us(10);
      encoder_val = read_adc();
      return encoder_val;
   }



void main()
   { 
   
      set_tris_a(0x00000001);                    //RA0 input
      setup_adc_ports(AN0);
      setup_adc(ADC_CLOCK_INTERNAL);
      setup_oscillator(OSC_4MHZ);
      output_a(0);
      int ADC_val=0;
     
      int change_counter=0;   //low high change counter
      byte change_STATUS=0;    //low high control status
      while(change_counter<=40)
         { 
            ADC_val = ADC_read();
            if(ADC_val<=100 && change_STATUS==0) 
               {
               OUTPUT_LOW(PIN_A5);
               change_counter++;
               change_STATUS=1;
               }
            else if(ADC_val>100 && change_STATUS==1)
               {
               OUTPUT_HIGH(PIN_A5);
               change_counter++;
               change_STATUS=0;
               }
         }
      output_high(PIN_A4);   //give warning that code has ended
      delay_ms(2000);
   }
   

and my motor drive code (this works too):
Code:

#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=4000000)

#define enable_pin PIN_A3   //pin1 on l293d
#define motor_pin1 PIN_A1   //pin2 on l293d
#define motor_pin2 PIN_A2   //pin7 on l293d


void motor_forward()
   {
      OUTPUT_HIGH(motor_pin1);
      OUTPUT_LOW(motor_pin2);
   }
   
void motor_backward()
   {
      OUTPUT_HIGH(motor_pin2);
      OUTPUT_LOW(motor_pin1);
   }

void motor_stop()
   {
      OUTPUT_LOW(motor_pin2);
      OUTPUT_LOW(motor_pin1);
   }

void main()
   { 
      setup_oscillator(OSC_4MHZ);
         while(1)
         {
           
            OUTPUT_HIGH(enable_pin);
            motor_forward();
            delay_ms(2000);
            motor_stop();
            delay_ms(1000);
            motor_backward();
            delay_ms(2000);
            motor_stop();
            delay_ms(1000);
         }
   }


and my final mix code (this does not work):
Code:
#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#device ADC=10
#use delay(clock=4000000)

#define encoder_data PIN_A0
#define enable_pin PIN_A3   //pin1 on l293d
#define motor_pin1 PIN_A1   //pin2 on l293d
#define motor_pin2 PIN_A2   //pin7 on l293d

unsigned int16 ADC_read()
   {
      unsigned int16 encoder_val=0;
      set_adc_channel(0);
      delay_us(10);
      encoder_val = read_adc();
      return encoder_val;
   }

void motor_forward()
   {
      OUTPUT_HIGH(motor_pin1);
      OUTPUT_LOW(motor_pin2);
   }
   
void motor_backward()
   {
      OUTPUT_HIGH(motor_pin2);
      OUTPUT_LOW(motor_pin1);
   }

void motor_stop()
   {
      OUTPUT_LOW(motor_pin2);
      OUTPUT_LOW(motor_pin1);
   }



void main()
   { 
   
      set_tris_a(0x00000001);                    //RA0 giriş
      setup_adc_ports(AN0);
      setup_adc(ADC_CLOCK_INTERNAL);
      setup_oscillator(OSC_4MHZ);
      int ADC_val=0;     
      int change_counter=0;   //low high değişimini sayan sayac
      byte change_STATUS=0;    //değişim olduğunu kontrol etme değişkeni
     
         while(change_counter<=40)
              {
               motor_forward();
               ADC_val = ADC_read();
                  if(ADC_val<=100 && change_STATUS==0)
                     {
                        OUTPUT_LOW(PIN_A5);
                        change_counter++;
                        change_STATUS=1;
                     }
                  else if(ADC_val>100 && change_STATUS==1)
                     {
                        OUTPUT_HIGH(PIN_A5);
                        change_counter++;
                        change_STATUS=0;
                     }
                  else
                     {
                     motor_forward();
                     delay_ms(50);
                     }
               }
         motor_stop();
         output_high(PIN_A4);
         delay_ms(2000);
      }
   


Last edited by doguhanpala on Mon Oct 10, 2016 2:28 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 07, 2016 7:02 am     Reply with quote

Quote:
#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#device ADC=10
#use delay(clock=4000000)

You have two oscillator fuses. Typically, HSPLL (with PLL5) is used if you
have an external 20 MHz crystal and want to run the PIC at 48 MHz.
INTRC_IO is typically used if you want to run the PIC without a crystal
and use the internal oscillator at 4 MHz.

What do you want to do ? If you don't want HSPLL, then remove that fuse.
temtronic



Joined: 01 Jul 2010
Posts: 9250
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Oct 07, 2016 7:07 am     Reply with quote

also...seems a shame to run that PIC at only 4MHz as it can go a LOT faster allowing you to do more !

Jay
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 1:42 am     Reply with quote

PCM programmer wrote:
Quote:
#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#device ADC=10
#use delay(clock=4000000)

You have two oscillator fuses. Typically, HSPLL (with PLL5) is used if you
have an external 20 MHz crystal and want to run the PIC at 48 MHz.
INTRC_IO is typically used if you want to run the PIC without a crystal
and use the internal oscillator at 4 MHz.

What do you want to do ? If you don't want HSPLL, then remove that fuse.


thank you so much. it worked.
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 1:42 am     Reply with quote

temtronic wrote:
also...seems a shame to run that PIC at only 4MHz as it can go a LOT faster allowing you to do more !

Jay


can it go faster with internal clock? or should i use crystal?
Ttelmah



Joined: 11 Mar 2010
Posts: 19559

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 2:12 am     Reply with quote

Understand. This is a USB PIC, and to use USB, it _requires_ a crystal. If you are not using, and don't intend to use USB, then use another chip. You gain three more useable pins straight away....

You can go to 8MHz without a crystal, but not use USB.

The crystal it needs is 4, 8, 12, 16, 20 or 24MHz (it can run off external oscillators at 40, and 48MHz as well), but these are the values supported for a standard crystal.
With any of these oscillators/crystal, you can run the processor at the crystal frequency, or Fosc/2, /3, or /4, or at 48MHz, 32MHz, 24Mhz, or 16MHz.

Then the configuration is:

To run off the crystal frequency or a sub division of this, use 'XT' (for 4MHz), or 'HS' (for faster crystals). Then select CPUDIV to give this /1, /2, /3 or /4.

Select PLLx, to give 4Mhz from your selected crystal ('x' here is a division). So with a 12Mhz crystal, select PLL3. This is needed even if you are running straight off the crystal, if you intend to use USB.

To run at the 16, 24, 32 or 48MHz frequencies instead use XTPLL or HSPLL depending on the crystal frequency chosen.
Look at table 2-3 in the data sheet. This gives input frequencies in the left column. The next column is the PLLx number. The next the oscillator selection. Then the CPUDIV number, and finally the clock speed the CPU will run.

So with a 12MHz crystal, to run at 24Mhz, you use:

HSPLL, CPUDIV3, PLL3

This is the block of the table starting '12MHz', and then entry highlighted in black (this is because it is one of the entries that supports both low speed, and full speed USB).


Last edited by Ttelmah on Mon Oct 10, 2016 2:29 am; edited 1 time in total
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 2:17 am     Reply with quote

Ttelmah wrote:
Understand. This is a USB PIC, and to use USB, it _requires_ a crystal. If you are not using, and don't intend to use USB, then use another chip. You gain three more useable pins straight away....

You can go to 8MHz without a crystal, but not use USB.

The crystal it needs is 4, 8, 12, 16, 20 or 24MHz (it can run off external oscillators at 40, and 48MHz as well), but these are the values supported for a standard crystal.
With any of these oscillators/crystal, you can run the processor at the crystal frequency, or Fosc/2, /3, or /4, or at 48MHz, 32MHz, 24Mhz, or 16MHz.

Then the configuration is:

To run off the crystal frequency or a sub division of this, use 'XT' (for 4MHz), or 'HS' (for faster crystals). Then select CPUDIV to give this /1, /2, /3 or /4.

Select PLLx, to give 4Mhz from your selected crystal ('x' here is a division). So with a 12Mhz crystal, select PLL3. This is needed even if you are running straight off the crystal, if you intend to use USB.

To run at the 16, 24, 32 or 48MHz frequencies instead use XTPLL or HSPLL depending on the crystal frequency chosen.
Look at table 2-3 in the data sheet. This gives input frequencies in the left column. The next column is the PLLx number. The next the oscillator selection. Then the CPUDIV number, and finally the clock speed the CPU will run.

So with a 12MHz crystal, to run at 24Mhz, you use:

HSPLL, CPUDIV2, PLL3

This is the block of the table starting '12MHz', and then entry highlighted in black (this is because it is one of the entries that supports both low speed, and full speed USB).


Thank you so much! I am new to pic and probably asking really stupid questions. Thank you for your patience also.
Ttelmah



Joined: 11 Mar 2010
Posts: 19559

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 2:31 am     Reply with quote

A couple of other comments that haven't been made yet:

First, 'ADC_CLOCK_INTERNAL', is not recommended above oscillator speeds of 1Mhz. This needs a look at the data sheet.

Then you do realise that your current code, after 40 moves, will stop and die?. Won't then do anything.

Also, just select the ADC channel once. Then when you arrive back at the 'read' code, provided there has been at least 10uSec since the last time you read the ADC, you can just read it again straight away, without needing any delay.
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 4:14 am     Reply with quote

Ttelmah wrote:
A couple of other comments that haven't been made yet:

First, 'ADC_CLOCK_INTERNAL', is not recommended above oscillator speeds of 1Mhz. This needs a look at the data sheet.

Then you do realise that your current code, after 40 moves, will stop and die?. Won't then do anything.

Also, just select the ADC channel once. Then when you arrive back at the 'read' code, provided there has been at least 10uSec since the last time you read the ADC, you can just read it again straight away, without needing any delay.


I know my code dies after 40 moves. It was for testing. Thanks for the warning. I had not realised i selected adc channel more than once. Thank you so much!
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