View previous topic :: View next topic |
Author |
Message |
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
Motor Control Code |
Posted: Fri Nov 06, 2015 2:46 pm |
|
|
Hi, I seem to be having some difficulty regarding my code. The hardware is set up correctly, i.e. i am receiving varying voltages from LDR's and IR sensors. However, I am not getting the motors to be controlled in the desired fashion (they are not doing anything). Any advice? I am using a PIC16F877a Microcontroller, 2 DC motors, 2 LEDS and 2 LDRs, 2 IR sensors.
Code: |
#include <16f877a.h> //set up microcontroller
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay (clock=20000000)
#define WHITE_LED_FRONT PIN_B6 //digital output //define pin allocation
#define WHITE_LED_REAR PIN_B7 //digital output
#define LDR_FRONT PIN_E2 //analogue input Channel 7
#define LDR_REAR PIN_A1 //analogue input Channel 1
#define IR_LEFT PIN_E1 //analogue input Channel 6
#define IR_RIGHT PIN_E0 //analogue input Channel 5
#define POWER_ON PIN_A4 //digital input
#define MOTOR_FORWARD_LEFT PIN_B5 //digital output
#define MOTOR_REVERSE_LEFT PIN_B3 //digital output
#define MOTOR_FORWARD_RIGHT PIN_B2 //digital output
#define MOTOR_REVERSE_RIGHT PIN_B1 //digital output
#define CUTOFF_LDR_FRONT 128 //define cutoffs
#define CUTOFF_LDR_REAR 128
#define CUTOFF_IR_LEFT 128
#define CUTOFF_IR_RIGHT 128
void wait_for_power_on() //set up power input
{
while(input(POWER_ON));
while(!input(POWER_ON));
delay_ms(100);
}
void sensor(int sensor) //define sensor function
{
output_high(MOTOR_FORWARD_LEFT); //switch off both motors
output_high(MOTOR_FORWARD_RIGHT);
output_high(MOTOR_REVERSE_LEFT);
output_high(MOTOR_REVERSE_RIGHT);
switch(sensor)
{
case 0: output_low(MOTOR_FORWARD_LEFT); output_low(MOTOR_REVERSE_LEFT); break; //Spin
case 1: output_low(MOTOR_FORWARD_LEFT); output_low(MOTOR_FORWARD_RIGHT); break; //Move forward
case 2: output_low(MOTOR_FORWARD_RIGHT); break; //Rotate left
case 3: output_low(MOTOR_FORWARD_LEFT); break; //Rotate right
case 4: output_low(MOTOR_REVERSE_LEFT); output_low(MOTOR_REVERSE_RIGHT); break; //Move back
}
}
void main()
{
int left_sensor;
int right_sensor;
int front_sensor;
int rear_sensor; //define sensor variables
setup_adc_ports(All_Analog); //set up ADC
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(6); //set up left sensor
left_sensor = read_adc();
set_adc_channel(5); //set up right sensor
right_sensor = read_adc();
set_adc_channel(7); //set up front sensor
front_sensor = read_adc();
set_adc_channel(1); //set up rear sensor
rear_sensor = read_adc();
while(true)
{
wait_for_power_on(); //wait for power switch to be turned on
delay_ms(1000);
output_high(WHITE_LED_FRONT); //switch on LED's for line sensors
output_high(WHITE_LED_REAR);
}
while(true)
{
if(left_sensor<CUTOFF_IR_LEFT) //Opponent seen on left sensor
if(right_sensor<CUTOFF_IR_RIGHT) //Opponent in front
sensor(1); //move forward
else //opponent on left
sensor(2); //rotate left
else if(right_sensor<CUTOFF_IR_RIGHT) //opponent seen on right side
sensor(3); //rotate right
else if(front_sensor<CUTOFF_LDR_FRONT) //line seen on front LDR
sensor(4); // move backwards
else if(rear_sensor<CUTOFF_LDR_REAR) //line seen on rear LDR
sensor(1); //move forwards
else
sensor(0); //spin
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 06, 2015 3:06 pm |
|
|
Quote: | However, I am not getting the motors to be controlled in the desired
fashion (they are not doing anything). |
Just make a very simple program without all the input sensor code.
Turn on one motor. Does it work ? If not, then look closely at your
motor control circuit. Post a link to the schematic of the circuit.
Also, your A/D code is wrong. You need to make the changes shown
in bold below:
Quote: |
setup_adc_ports(All_Analog); //set up ADC
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(6); //set up left sensor
delay_us(20);
eft_sensor = read_adc();
set_adc_channel(5); //set up right sensor
delay_us(20);
right_sensor = read_adc();
set_adc_channel(7); //set up front sensor
delay_us(20);
front_sensor = read_adc();
set_adc_channel(1); //set up rear sensor
delay_us(20);
rear_sensor = read_adc();
|
The 20us delay time is shown in EQUATION 11-1: ACQUISITION TIME
in the 16F877 data sheet.
The A/D clock divisor of 32 is shown in TABLE 11-1: TAD vs. MAXIMUM
DEVICE OPERATING FREQUENCIES (STANDARD DEVICES (C)) in the
16F877 data sheet. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Nov 06, 2015 3:15 pm |
|
|
the choice of the 877 is a bad one if you ever intend to manufacture more than ONE of these. based on price and based on performance. the 877 is a "school kid" part not a design-for-manufacturing part.
the 16f887 for a superior device at less than 1/2 the price.
in the 877 data sheet did you read this ?
Quote: |
re the ADC clock selection ......
e 1: The RC source has a typical TAD time of 4 µs but can vary between 2-6 µs.
2: When the device frequencies are greater than 1 MHz, the RC A/D conversion clock source is only
recommended for Sleep operation.
|
were you going to use it in sleep?
the process of getting your sensors is assured to be SLOWER than need be
and much noisier from reading to reading than it has to be.
But that doesn't matter either ;-))
look closely at your code !
After that initial reading of the ADC -
you enter a while loop and never read the adc again.
whats with THAT ???
what kind of decisions does that make for ?
------------------------
(( i see PCM_P commented on the above as i was writing))
also
sensor() is CRAZY -
look at what you are doing to those (drive?) lines !!!
switches like what you program are NASTY into reactive loads.
think about what happens if sensor is called with either motor ON -and
then re-selected to be ON again?
ouch.....
itd
your code is a MESS.......... |
|
|
wangine
Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania
|
|
Posted: Fri Nov 06, 2015 5:39 pm |
|
|
also , two while(1) loops
Code: | while(true)
{
wait_for_power_on(); //wait for power switch to be turned on
delay_ms(1000);
output_high(WHITE_LED_FRONT); //switch on LED's for line sensors
output_high(WHITE_LED_REAR);
}
| Your code will never go out from here , just turn on the leds, wait and ..... again. |
|
|
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
Motor Control Code |
Posted: Sat Nov 07, 2015 11:39 am |
|
|
I have altered the code (see below) and I have also attached the circuit design.
Code: |
#include <16f877a.h> //set up microcontroller
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay (clock=20000000)
#define WHITE_LED_FRONT PIN_B6 //digital output //define pin allocation
#define WHITE_LED_REAR PIN_B7 //digital output
#define LDR_FRONT PIN_E2 //analogue input Channel 7
#define LDR_REAR PIN_A1 //analogue input Channel 1
#define IR_LEFT PIN_E1 //analogue input Channel 6
#define IR_RIGHT PIN_E0 //analogue input Channel 5
#define POWER_ON PIN_B4 //digital input
#define MOTOR_FORWARD_LEFT PIN_B5 //digital output
#define MOTOR_REVERSE_LEFT PIN_B3 //digital output
#define MOTOR_FORWARD_RIGHT PIN_B2 //digital output
#define MOTOR_REVERSE_RIGHT PIN_B1 //digital output
#define CUTOFF_LDR_FRONT 128 //define cutoffs
#define CUTOFF_LDR_REAR 128
#define CUTOFF_IR_LEFT 128
#define CUTOFF_IR_RIGHT 128
void wait_for_power_on() //set up power input
{
while(input(POWER_ON));
delay_ms(100);
}
void sensor(int sensor) //define sensor function
{
output_high(MOTOR_FORWARD_LEFT); //switch off both motors
output_high(MOTOR_FORWARD_RIGHT);
output_high(MOTOR_REVERSE_LEFT);
output_high(MOTOR_REVERSE_RIGHT);
switch(sensor)
{
case 0: output_low(MOTOR_FORWARD_LEFT); output_low(MOTOR_REVERSE_LEFT); break; //Spin
case 1: output_low(MOTOR_FORWARD_LEFT); output_low(MOTOR_FORWARD_RIGHT); break; //Move forward
case 2: output_low(MOTOR_FORWARD_RIGHT); break; //Rotate left
case 3: output_low(MOTOR_FORWARD_LEFT); break; //Rotate right
case 4: output_low(MOTOR_REVERSE_LEFT); output_low(MOTOR_REVERSE_RIGHT); break; //Move back
}
}
void main()
{
int left_sensor;
int right_sensor;
int front_sensor;
int rear_sensor; //define sensor variables
setup_adc_ports(All_Analog); //set up ADC
setup_adc(ADC_CLOCK_DIV_32);
while(true)
{
set_adc_channel(6); //set up left sensor
delay_us(20);
left_sensor = read_adc();
set_adc_channel(5); //set up right sensor
delay_us(20);
right_sensor = read_adc();
set_adc_channel(7); //set up front sensor
delay_us(20);
front_sensor = read_adc();
set_adc_channel(1); //set up rear sensor
delay_us(20);
rear_sensor = read_adc();
wait_for_power_on(); //wait for power switch to be turned on
delay_ms(5000);
output_low(WHITE_LED_FRONT); //switch on LED's for line sensors
output_low(WHITE_LED_REAR);
if(left_sensor<CUTOFF_IR_LEFT) //Opponent seen on left sensor
if(right_sensor<CUTOFF_IR_RIGHT) //Opponent in front
sensor(1); //move forward
else //opponent on left
sensor(2); //rotate left
else if(right_sensor<CUTOFF_IR_RIGHT) //opponent seen on right side
sensor(3); //rotate right
else if(front_sensor<CUTOFF_LDR_FRONT) //line seen on front LDR
sensor(4); // move backwards
else if(rear_sensor<CUTOFF_LDR_REAR) //line seen on rear LDR
sensor(1); //move forwards
else
sensor(0); //spin
}
}
|
https://drive.google.com/file/d/0Byue2b0J82tjTXIxcUR3YmxDVXc/view?usp=sharing |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 07, 2015 2:30 pm |
|
|
The schematic shows an L293D motor controller chip. You don't show the
PIC in that schematic. Also, you don't show the +5v power supply.
You're not showing us enough.
In your code, you have a routine where you wait for the power switch:
Code: | void wait_for_power_on() //set up power input
{
while(input(POWER_ON));
delay_ms(100);
} |
You are waiting until Pin B4 goes to a low level. Then you will exit the
while() loop above. Where is this shown in your schematic ? Where is
there a pin that goes to a low level (ground) when power is turned on ?
I still say you need to setup a test where you turn on one motor just
to see if it will run. Don't look at sensors or anything else. You need
to do this test. It will prove:
1. That your hardware is correct or not.
2. That you have the correct software method of controlling the L293D
to enable turning on a motor. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Nov 07, 2015 6:10 pm |
|
|
Code: | void sensor(int sensor) //define sensor function |
I also suggest you change these names to be more in line with the actual function they perform: Code: | void move(int direction) // Set motors to move in given direction |
Even nicer when you use defines or an enum for the direction values.
A line like: Code: | sensor(1); //move forward |
then becomes: Code: | #define FORWARD 1
move(FORWARD); | Note that no comments are needed anymore to explain what's happening; the code has become self documenting. |
|
|
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
Motor Control Code |
Posted: Mon Nov 09, 2015 6:43 am |
|
|
The motors will turn if a simple output is made to the H-bridge. However, with my code, there is approximately a 3.3V going into all 4 of the H-bridge inputs. Obviously, this is why the motors aren't turning. With regards to the code, I know it can do with a bit of tidying up. I just want to get the code to do what I want it to do first before cleaning it up. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Nov 09, 2015 8:37 am |
|
|
This almost certainly goes back to this comment from PCM_Programmer:
Quote: |
You are waiting until Pin B4 goes to a low level. Then you will exit the
while() loop above. Where is this shown in your schematic ? Where is
there a pin that goes to a low level (ground) when power is turned on ?
|
Unless this pin is seen going low, your code will leave the driver pins still set as inputs, so they will float to whatever the L293D produces on it's inputs when no connection is made. Typically about 3v. |
|
|
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
|
|
wangine
Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania
|
Re: Motor Control Code |
Posted: Tue Nov 10, 2015 10:25 pm |
|
|
Jammie1000000 wrote: | I have brought the power on into the main while code, so should it not loop in this? I.e. checking to see if power is on, making sure the LED's are lit, then controlling the motor? I have attached the flow chart of what I want the microcontroller to do.
|
According with your flowchart should add a _status_power_flag_ in your power function if you want to follow that chart. All loop functions will check that flag otherwise your power function don't make sense.
Also my advice is to clean up all your code and to start add, all functions, step by step like your chart show. I don't think will take more that 20 min
First off all be sure the motor or motors running, and only after that can add the conditions, otherwise you will stay forever to think why... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 10, 2015 11:24 pm |
|
|
Code: | #define POWER_ON PIN_B4 |
Post a schematic that shows the circuit that is connected to Pin B4 on the PIC.
Post a schematic that shows your PIC and all external circuits. |
|
|
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 12, 2015 2:04 pm |
|
|
Your schematic is very low resolution. Zooming in just makes it harder
to read. Your circuit appears to look like this:
Code: |
NC +V(+5v)
/o |
Pic / | _____
pin -----/ o--------o----->|-----|_____|-------
B4 NO Led 220 ohms |
-----
--- Gnd
|
This means pin B4 will either be floating or be connected to +5v.
"Floating" means the pin has nothing connected to it, and could be
any value. It might read a logic 0, or if the switch was previously pressed
for just a short time, it could easily stay at a high logic level and your
PIC would read that as a logic 1.
Also, the switch has nothing to do with "power on". It doesn't control
the power. It's more like a "Start" switch, that you press to tell the
PIC to begin running the motor control program.
You should remove your existing switch circuit. You need to change it
to a Start switch circuit that looks like this:
Code: | +5v
|
<
> 4.7K NC
< /o
To | /
PIC --------o--------/ o--------
pin B4 NO |
-----
--- Gnd
- |
Then change your "power on" function to this:
Code: |
#define START_SWITCH PIN_B4
void wait_for_start(void)
{
while(input(START_SWITCH)); // Wait until start button is pushed
} |
This routine will wait in a loop until a logic 0 is read from Pin B4.
The 4.7K pullup will provide a logic 1 until the switch is pressed,
and then the PIC will read a logic 0 (ground). Then the routine
will leave the while() loop and return to the main() code and
your motor control code can begin to run. |
|
|
Jammie1000000
Joined: 06 Nov 2015 Posts: 8
|
Motor control code |
Posted: Thu Nov 12, 2015 2:55 pm |
|
|
The power on doesn't seem to be a problem. When the button is pressed, the leds come on. The problem seems to be the motor control and I'm getting 3v from each of the four motor outputs into the h bridge. |
|
|
|