|
|
View previous topic :: View next topic |
Author |
Message |
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
Analog Read and Motor Drive 18F2550 SOLVED |
Posted: Fri Oct 07, 2016 4:40 am |
|
|
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
|
|
Posted: Fri Oct 07, 2016 7:02 am |
|
|
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: 9247 Location: Greensville,Ontario
|
|
Posted: Fri Oct 07, 2016 7:07 am |
|
|
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
|
|
Posted: Mon Oct 10, 2016 1:42 am |
|
|
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
|
|
Posted: Mon Oct 10, 2016 1:42 am |
|
|
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: 19554
|
|
Posted: Mon Oct 10, 2016 2:12 am |
|
|
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
|
|
Posted: Mon Oct 10, 2016 2:17 am |
|
|
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: 19554
|
|
Posted: Mon Oct 10, 2016 2:31 am |
|
|
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
|
|
Posted: Mon Oct 10, 2016 4:14 am |
|
|
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! |
|
|
|
|
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
|