|
|
View previous topic :: View next topic |
Author |
Message |
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
Interrupt with motor drive and encoder 18f2550 solved |
Posted: Wed Oct 12, 2016 8:07 am |
|
|
Hello
I try to drive a motor and stop it with the data that i collect from optical encoder. I want to do it with interrupt. I have a few questions.
First of all, i did not get it how the pic knows which function is the interrupt function. Does it understand when the function ends with ISR() ?
If i use 2 encoders and write 2 interrupt functions like external_interrupt1_isr() and external_interrupt2_isr(), how will it understand which interrupt function will start with 2 different data ?
My last question. I wrote the code below. It seems the interrupt function doesn't work. I connected an led to pin b2 and it does not light.
Note: I checked the motor and circuit with different software and they work correctly. I checked the interrupt code too. It works also. I added them below. The problem is i cannot mix them. Something is wrong. Any ideas?
Note2: I use L293d for motor driving if it makes any difference.
Doğuhan
this is the interrupt code. it works.
Code: | #include <18F2550.h>
#fuses INTRC_IO,HS, NOWDT, PUT, NOLVP, HSPLL,NOMCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN,NOPUT
#device ADC=10
#use delay(clock=4000000)
#int_EXT
void external_interrupt_isr()
{
output_high(PIN_B2); //open interrupt led
}
void main()
{
//setup lines
set_tris_b(0b1); //b0 is input, the voltage from the switch goes there
ext_int_edge(L_TO_H);
setup_oscillator(OSC_4MHZ);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(GLOBAL);
while(TRUE)
{
output_low(PIN_B2); //close the interrupt led
output_high(PIN_B1); //blink led1
delay_ms(500);
output_low(PIN_B1);
delay_ms(500);
}
}
|
this is the motor drive code. it also 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)
#define motor1_pin1 PIN_A1 //pin2 on l293d
#define motor1_pin2 PIN_A2 //pin7 on l293d
#int_EXT
unsigned int speed=100;
//motor komutları
void motor1_Forward() //motor 1 ileri
{
OUTPUT_HIGH(motor1_pin1);
OUTPUT_LOW(motor1_pin2);
}
void motor1_Backward() //motor 1 geri
{
OUTPUT_HIGH(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
}
void motor1_Stop() //motor 1 dur
{
OUTPUT_LOW(motor1_pin2);
OUTPUT_HIGH(motor1_pin1);
delay_ms(10);
OUTPUT_HIGH(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
delay_ms(10);
OUTPUT_LOW(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
}
void main()
{
set_tris_a(0x00000001);
set_tris_b(0b11);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_oscillator(OSC_4MHZ);
setup_timer_2(T2_DIV_BY_16,250,1);
setup_CCP1(CCP_PWM); // pin 1 on l293d
set_pwm1_duty(speed);
while(TRUE)
{
motor1_Forward();
}
}
|
the last one, ithink the distance_counter does not increase, which means the interrupt function doesnt work. i could not find the problem.
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 motor1_pin1 PIN_A1 //pin2 on l293d
#define motor1_pin2 PIN_A2 //pin7 on l293d
#int_EXT
unsigned int distance_counter=0;
void external_interrupt_isr()
{
distance_counter=distance_counter+1;
}
unsigned int speed=100;
//motor functions
void motor1_Forward()
{
OUTPUT_HIGH(motor1_pin1);
OUTPUT_LOW(motor1_pin2);
}
void motor1_Backward()
{
OUTPUT_HIGH(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
}
void motor1_Stop()
{
OUTPUT_LOW(motor1_pin2);
OUTPUT_HIGH(motor1_pin1);
delay_ms(10);
OUTPUT_HIGH(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
delay_ms(10);
OUTPUT_LOW(motor1_pin2);
OUTPUT_LOW(motor1_pin1);
}
void main()
{
set_tris_a(0x00000001);
set_tris_b(0x00000001);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_oscillator(OSC_4MHZ);
setup_timer_2(T2_DIV_BY_16,250,1);
setup_CCP1(CCP_PWM); // pin 1 on l293d
set_pwm1_duty(speed);
ext_int_edge(L_TO_H);
setup_oscillator(OSC_4MHZ);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(GLOBAL);
output_high(PIN_B2); //led blink once to see the program started
delay_ms(1000);
output_low(PIN_B2);
delay_ms(1000);
while(TRUE)
{
if(distance_counter<=40)
{
motor1_Forward();
}
else
{
motor1_Stop();
delay_ms(2000);
output_high(PIN_B2);
}
}
}
|
Last edited by doguhanpala on Fri Oct 21, 2016 1:24 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Oct 12, 2016 8:21 am |
|
|
The #INT_EXT line says that the routine on the following line is the handler for the EXT isr.
Though it should just ignore the white-space lines, the syntax should be:
Code: |
#INT_EXT //This declares that the following subroutine is for INT_EXT
void external_interrupt_isr(void)
{
output_high(PIN_B2); //open interrupt led
}
|
The handler for INT_EXT1, would want #INT_EXT1 in front of it etc...
Don't put variable declarations between this and the function
Your oscillator settings are wrong. You currently have three oscillators setup.
INT_RC (use the internal oscillator)
HS use the external crystal directly
HSPLL use the external crystal with a PLL
Duh.....
I've pointed out how the settings work, only a few days ago in this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=55555>
You also have both the power up time, and no power up timer selected. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Thu Oct 13, 2016 1:11 am |
|
|
I deleted the HS and HSPLL. Still doesn't work. And the other 2 code works perfectly even though i did not change the fuses or the other things you mentioned. Why do they work correctly?
and thanks for your help. i really appreciate it. i am dealing with pic with max 2 weeks and since i don't know how to choose fuses, or what is timer, i find the codes i need. So fuses can be ridiculous.
I have one more question. If i want to use 2 interrupts same time, can i write this?
Code: |
#INT_EXT1 //This declares that the following subroutine is for INT_EXT
void external_interrupt_isr(void)
{
output_high(PIN_B2); //open interrupt led
}
#INT_EXT2
void external_interrupt_isr(void)
{
output_low(PIN_B2); //close interrupt led
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Oct 13, 2016 1:31 am |
|
|
Yes, except the remark is now wrong. INT_EXT1, is for EXT1, not for EXT, and it can't then work, since you are using pin B2 as an output, and also as an input.
INT_EXT, is pin B0
INT_EXT1 is pin B1
INT_EXT2 is pin B2
You have this latter pin being both driven high/low, and also used as an interrupt input.
Working. Luck.
The fuses 'or' together, so the result may be acceptable or may not. If you look at the end of the .LST file, it'll show what really is being sent to the chip.
There is also FSCM. This is a system where if the specified oscillator doesn't work, the chip will 'fall back' and run off the internal oscillator (fail safe clock monitor). So chips can work a bit, but are not working as they should....
You will find that things that are wrong, can sometimes work. More often than not they will have later problems. What actually _is_ your clock?. Do you have a crystal?. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Thu Oct 13, 2016 1:35 am |
|
|
Ttelmah wrote: | Yes, except the remark is now wrong. INT_EXT1, is for EXT1, not for EXT, and it can't then work, since you are using pin B2 as an output, and also as an input.
INT_EXT, is pin B0
INT_EXT1 is pin B1
INT_EXT2 is pin B2
You have this latter pin being both driven high/low, and also used as an interrupt input. |
thank you so much! |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Fri Oct 14, 2016 5:12 am |
|
|
Ttelmah wrote: | Yes, except the remark is now wrong. INT_EXT1, is for EXT1, not for EXT, and it can't then work, since you are using pin B2 as an output, and also as an input.
INT_EXT, is pin B0
INT_EXT1 is pin B1
INT_EXT2 is pin B2
You have this latter pin being both driven high/low, and also used as an interrupt input.
Working. Luck.
The fuses 'or' together, so the result may be acceptable or may not. If you look at the end of the .LST file, it'll show what really is being sent to the chip.
There is also FSCM. This is a system where if the specified oscillator doesn't work, the chip will 'fall back' and run off the internal oscillator (fail safe clock monitor). So chips can work a bit, but are not working as they should....
You will find that things that are wrong, can sometimes work. More often than not they will have later problems. What actually _is_ your clock?. Do you have a crystal?. |
I will use crystal. Just not for now. For this part of project i don't use crystal. I am trying to do my part properly. My friends will complete their parts and the crystal will take place on their parts. When we mix the parts we do, i will change the fuses and stop using internal clock. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Wed Oct 19, 2016 6:28 pm |
|
|
Don't have too much to add after Mr Ttelmah posts, but your sentence:
Quote: | since i don't know how to choose fuses, or what is timer... |
How you can write software if the sentence above is true?
You need to invest time to read (and understand) the data sheet first!!!
Proposing you to write first a short program using one of the timers to make a led to blink every second.
Best wishes
Joe |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Wed Oct 19, 2016 11:53 pm |
|
|
gjs_rsdi wrote: | Don't have too much to add after Mr Ttelmah posts, but your sentence:
Quote: | since i don't know how to choose fuses, or what is timer... |
How you can write software if the sentence above is true?
You need to invest time to read (and understand) the data sheet first!!!
Proposing you to write first a short program using one of the timers to make a led to blink every second.
Best wishes
Joe |
First of all, thank you for your warning. I usually search what i need to write a software. For example i need to stop a motor when i press the button. First i search how to drive a motor. After watching videos and reading forums ianage it. When i make it i search external interrupts. After a bit of work and try i usually achieve what i need.
But i realised it is not the best way to do it. My softwares work so far but i know i am just saving the day.
Thank you for warning again.
Best wishes
Doğuhan |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Oct 20, 2016 6:53 am |
|
|
Let's make some comments:
First thing is that the normal way to detect a quadrature encoder will be to use two of the 'interrupt on change' bits (B4 to B7). A quadrature encoder has two waveforms 90 degrees out of phase of each other, and to decode the four states, you want to be calling the scan code on all four edges that this involves (signals A, and B, each going high or low). Quadrature code has been posted here many times. Advantage of using the interrupt on change, is just one routine is needed to handle all four edges.
Then, as I have already pointed out, you cannot use USB with the internal oscillator (there are chips where you can - these have either much more accurate internal oscillators, so can do 'low speed' USB, using this - or have the ability to synchronise the USB to the clock coming from the master device). Now if you are attempting to produce some form of motor controlled by USB, you are not going to get very far without the USB.....
Then we have the oscillator/fuses question. There are dozens of tiny details in every PIC, that need to be understood. Things like just how poor the accuracy of the ADC will be when you use the supply as the reference. What clocks can be used for which jobs, what the limitations of speeds and voltage levels are. All of these need study. Though you don't have to know every page of the data sheet (things like just 'how' the memory is laid out, and what registers are where, are handled for you by the compiler), you need to be looking at the basics on the oscillator, fuses etc., and at the specifics of the peripherals you are trying to use.
Now, if you are doing anything like a PID design (so the motor accelerates and moves 'to' a specific location etc.), your code will need to become synchronous. Taking readings at a fixed interval, so it can adjust the motor PWM. Otherwise when timing changes, the movement will be erratic. |
|
|
|
|
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
|