|
|
View previous topic :: View next topic |
Author |
Message |
spudtheimpaler
Joined: 16 Mar 2005 Posts: 6 Location: Birmingham University
|
polling |
Posted: Wed Mar 16, 2005 7:37 am |
|
|
Hi all. I am having some serious trouble with what should be a very simple problem.
I am in a group trying to design a line following robot for a university project. We have three sensors which are active low on the line and high off the line (Due to inverting op-amp amplification) so when we input we should have a variable
sensorValue = input_d();
sensorValue being 0x05 (101) if moving forward along the line, 0x01 (001)if it is turning right and need to turn left, and 0x04 (100) if we need to turn right. As such, i wrote the simple code below to test the sensors.
Code: |
////////////////////////////////
//
//
// EE2G2 Robot Code
// Group 29
// possible_interupt_code.c
// 10/03/05
// Auther: Mitchell Kent
// Editors:
//
//
// This is code to try out the motor lookup tables routines
//
//
////////////////////////////////
#include <16F877.h>
#use delay(clock=10000000)
#fuses NOWDT,XT, NOPUT, NOPROTECT
#define FOREVER 1
const int LOOKUPTABLE_F[8] = { 0xcc, 0x44, 0x66, 0x22, 0x33, 0x11, 0x99, 0x88 };
const int LOOKUPTABLE_L[16] = { 0xcc, 0xc4, 0x46, 0x42, 0x63, 0x61, 0x29, 0x28, 0x3c, 0x34, 0x16, 0x12, 0x93, 0x91, 0x89, 0x88 }; //This code should run the right wheel twice for every once of the left, thus turning right overall.};
const int LOOKUPTABLE_R[16] = { 0xcc, 0x4c, 0x64, 0x24, 0x36, 0x16, 0x92, 0x82, 0xc3, 0x43, 0x61, 0x21, 0x39, 0x19, 0x98, 0x88 }; //This code should run the left wheel twice for every once of the right, thus turning right overall.
const int LOOKUPTABLE_FULL_F[4] = { 0x66, 0x33, 0x99, 0xcc };
const int LOOKUPTABLE_FULL_R[8] = { 0x66, 0x36, 0x93, 0xc3, 0x69, 0x39, 0x9c, 0xcc };
const int LOOKUPTABLE_FULL_L[8] = { 0x66, 0x63, 0x39, 0x3c, 0x96, 0x93, 0xc9, 0xcc };
volatile int sensorValue = 0x01;
int index = 0;
main()
{
output_high(PIN_A0);
delay_ms(5);
while( 1 )
{
sensorValue=0x00;
sensorValue=input_d();
delay_cycles(1);
if(sensorValue == 0x01)
{
//Move Right
for(index = 0; index<8; index++) //loop throughout the table
{
output_c(LOOKUPTABLE_FULL_R[index]); //Use the right direction lookup table
delay_ms(150);
}
}
else if(sensorValue == 0x05)
{
//Move forwards
for(index = 0; index<4; index++)
{
output_c(LOOKUPTABLE_FULL_F[index]); //Use the lookup table that sends both motors at the same pace
delay_ms(150);
}
}
else if(sensorValue == 0x04 )
{
//Move Left
for(index = 0; index<8; index++)
{
output_c(LOOKUPTABLE_FULL_L[index]); ////Use the left direction lookup table
delay_ms(150);
}
}
else{ output_c(0xFF); delay_ms(4); } //I'll expliain this lines purpose shortly
output_low(PIN_B0);
delay_ms(4);
} //Exit while(1) loop
}// Exit Main
|
This appeared to work fine at first but showed odd behaviour. When the sensorValue was forward 0x05 the stepper motors (or leds showing stepper motor movement) moved as they should, the same left, and the same right. BUT after going forwards, then left, then right, then forwards (which all worked as expected) on turn left again the leds would indicate the pic was entering the last else state (output_d(0xFF)) And this happens reliably every time. you can go forwards, left, forwards, left, forwards, left, infinitely it would appear with expected behaviour, but once you turn right, it will never again go into the turn left else if statement.
Does anyone have an explanation for this odd behaviour? It isnt the chip, as i have tried on three different PIC16F877s all with the same effect.
I have tried if statements alone, else ifs, while loops, my current attempt is
Code: | ////////////////////////////////
//
//
// EE2G2 Robot Code
// Group 29
// possible_interupt_code.c
// 10/03/05
// Auther: Mitchell Kent
// Editors:
//
//
// This is code to try out the motor lookup tables routines
//
//
////////////////////////////////
#include <16F877.h>
#use delay(clock=10000000)
#fuses NOWDT,XT, NOPUT, NOPROTECT
#define FOREVER 1
const int LOOKUPTABLE_F[8] = {0xcc, 0x44, 0x66, 0x22, 0x33, 0x11, 0x99, 0x88 };
const int LOOKUPTABLE_L[16] = { 0xcc, 0xc4, 0x46, 0x42, 0x63, 0x61, 0x29, 0x28, 0x3c, 0x34, 0x16, 0x12, 0x93, 0x91, 0x89, 0x88 }; //This code should run the right wheel twice for every once of the left, thus turning right overall.};
const int LOOKUPTABLE_R[16] = { 0xcc, 0x4c, 0x64, 0x24, 0x36, 0x16, 0x92, 0x82, 0xc3, 0x43, 0x61, 0x21, 0x39, 0x19, 0x98, 0x88 }; //This code should run the left wheel twice for every once of the right, thus turning right overall.
const int LOOKUPTABLE_FULL_F[4] = { 0x66, 0x33, 0x99, 0xcc };
const int LOOKUPTABLE_FULL_R[8] = { 0x66, 0x36, 0x93, 0xc3, 0x69, 0x39, 0x9c, 0xcc };
const int LOOKUPTABLE_FULL_L[8] = { 0x66, 0x63, 0x39, 0x3c, 0x96, 0x93, 0xc9, 0xcc };
volatile int sensorValue = 0x01; //Make them volatile so a change in interrupt ALSO means a change in main
int index = 0;
main()
{
setup_adc_ports( NO_ANALOGS );
output_high(PIN_A0);
delay_ms(5);
while(1)
{
output_d(0xFF); //Vain attempt at flushing the input port
delay_cycles(1);
output_d(0x00);
delay_cycles(1);
set_tris_d(0xFF);
delay_cycles(1);
output_high(PIN_B0);
if(!input(PIN_D1))
{
if(!input(PIN_D0))
{
//Move Right
for(index = 0; index<16; index++) //loop throughout the table
{
output_c(LOOKUPTABLE_R[index]); //Use the right direction lookup table
delay_ms(50);
}
}
else if(!input(PIN_D2))
{
//Move Left
for(index = 0; index<16; index++)
{
output_c(LOOKUPTABLE_L[index]); //Use the left direction lookup table
delay_ms(50);
}
}
else
{
//Move Forwards
for(index = 0; index<8; index++)
{
output_c(LOOKUPTABLE_F[index]); //Use the lookup table that sends both motors at the same pace
delay_ms(50);
}
}
}
else{ output_c(0xFF); delay_ms(500); output_d(0x00); delay_ms(500); }
output_d(0xFF); //vain attempt to flush variable
delay_cycles(1);
output_d(0x00);
delay_cycles(1);
set_tris_d(0xFF);
output_low(PIN_B0);
delay_ms(4);
} //Exit while(1) loop
}// Exit Main
|
Can you see the desperation forming?
If there is anyone who can see any flaws in the code i would greatly appreciate it. I am desperate!
Many thanks
Mitch
PIC16f877
using 10MHz external crystal
inputs on port d outputs port c
Id tell you which compiler version im using, but cant find it in the help menu etc but its pcw c compiler ide on the top bar.
PS Is it common to have so much trouble posting here? I've had an error screen on preview posting in excess of ten times already, ive logged out and back in and everything! |
|
|
Ttelmah Guest
|
|
Posted: Wed Mar 16, 2005 8:05 am |
|
|
Are you sure about your return values?. Personally, I'd have expected that you might (in the 'turn right' example), see '011', sometimes instead of 001, depending on the responses of the sensors, and the width of the line. Remember that even if you have 'tested' the sensors with a meter, the responses at speed may well differ. Your 'turn' algorithm, is also quite violent, so the motion will not be smooth, and may make the tendency to overshoot worse.
My suspicion is that the sensitivity of the right and left sensors differs a little, and you are getting to this sort of 'unexpected' behaviour in one direction. This then results in hitting the last state.
I'd suggest testing with a switch statement like:
[code]
switch (sensorValue) {
case 0b001:
case 0b011:
//Here 'right'
break
case 0b101:
//Here straight
break;
case 0b100:
case 0b110:
//Here left
break;
}
You could also add tests for the 010 state (you have found a second line!), and the 111 state (you are off the line). Do this, rather tan adding a 'default', since the compiler will generate a faster 'table based' switch, if just the required states are present. You could consider seperating the '011', and '001' states, and turning more violently in one case.
Best Wishes |
|
|
Guest
|
Try this |
Posted: Wed Mar 16, 2005 8:08 am |
|
|
Your test with else if is not too clearl, As I read it a switch will do the same thing.
If this does not work I'd check the sensor values.
main()
{
output_high(PIN_A0);
delay_ms(5);
while( 1 )
{
sensorValue=0x00;
sensorValue=input_d();
delay_cycles(1);
switch(sensorValue)
{
case 0X01: // Move Right
for(index = 0; index<8; index++) //loop throughout the table
{
output_c(LOOKUPTABLE_FULL_R[index]); //Use the right direction lookup table
delay_ms(150);
}
break;
case 0x05: // Move forwards
for(index = 0; index<4; index++)
{
output_c(LOOKUPTABLE_FULL_F[index]); //Use the lookup table that sends both motors at the same pace
delay_ms(150);
}
break;
case 0x04: // Move Left
for(index = 0; index<8; index++)
{
output_c(LOOKUPTABLE_FULL_L[index]); ////Use the left direction lookup table
delay_ms(150);
}
break;
deafult:
output_c(0xFF); delay_ms(4);
break;
}
output_low(PIN_B0);
delay_ms(4);
} //Exit while(1) loop
}// Exit Main |
|
|
spudtheimpaler
Joined: 16 Mar 2005 Posts: 6 Location: Birmingham University
|
|
Posted: Wed Mar 16, 2005 8:15 am |
|
|
At present we are manually setting the sensors to give 0 or 1 values, IE the sensors aren't even plugged into the output, we're just using high/ low values - This way we know the input going in is what we expect.
I have plans for adding a more violent turn on the more extreme cases but i wanted to try and keep it simple whilst i was debugging the problem above.
So basically we know what the inputs are (which will eventually be from the sensors), was just windering why it was not entering the else if(sensorValue == 0x04), (when we know the sensor value SHOULD be 0x04 cause we are inputting it manually) when it should be.
I will however take you advice and write it in a switch(sensorValue){ case: setup - i didn't know this was valid in PIC C.
Thank you for looking over it, greatly appreciated!
Mitch |
|
|
GRR! Guest
|
|
Posted: Wed Mar 16, 2005 8:54 am |
|
|
GRR! Even with the switch clause the thing is not doing as its told :(
When we start the pic up in a particular state (by state, i'm referring to the different sensor setups) the apt switch case is implemented. If you then change the state, the correct case is implemented, but after that, if another change is made, kupput, the thing does something random. Well its not entirely random - if we do something in the default case, this is implemented, but there is no association between a known sensor state and what it is doing. |
|
|
Guest
|
|
Posted: Wed Mar 16, 2005 9:10 am |
|
|
spudtheimpaler wrote: | At present we are manually setting the sensors to give 0 or 1 values, IE the sensors aren't even plugged into the output, we're just using high/ low values - This way we know the input going in is what we expect.
I have plans for adding a more violent turn on the more extreme cases but i wanted to try and keep it simple whilst i was debugging the problem above.
So basically we know what the inputs are (which will eventually be from the sensors), was just windering why it was not entering the else if(sensorValue == 0x04), (when we know the sensor value SHOULD be 0x04 cause we are inputting it manually) when it should be.
I will however take you advice and write it in a switch(sensorValue){ case: setup - i didn't know this was valid in PIC C.
Thank you for looking over it, greatly appreciated!
Mitch |
How are you setting the sensor values ?
If it's by a mechanical switch you may get all sorts of values as the switch bounces.
The (code) switch will only respond to the case Value: and of course the default everytime there is no valid case.
Which is why I suggested using the switch.
I did not check your lookup table values because I don't know what they really do. Could you have a bad value ?
I'd say the Sensor of lookup table is to be investigated.
You say you are in a panic mode. Sometimes it helps to leave it alone got do somthing else and come back to it with a fresh mind.
Good luck.
Please report the problem, I harte it when people come here for help and never tell me what the solution was.
Hans W |
|
|
_Spudtheimpaler Guest
|
In response |
Posted: Wed Mar 16, 2005 9:33 am |
|
|
Hi, thanks for looking over it.
I am setting the sensor values by putting (or not putting! ) a 5v wire directly into the input port. Also i knwo the lookup tables are correct because we have had the leds flashing / stepper motors stepping as they should.
The problem arises after number of certain orders of inputs are detected. Ie sensor setup is set to one case value, then a different case value, then returned to the original case value. The first two changes are implemented by the case switch, but the third is not.
I think the problem lies with the value "sensorValue". Though why input_d(); would work the first few times and not others i dont understand, and within the loop prior to input_d(); i am putting sensorValue(0x00);
Tis most confuzzling.
Promise to post my solution, though i have spent about 3 days on it now.
Ta
Mitch |
|
|
_spudtheimpaler Guest
|
hmmm |
Posted: Wed Mar 16, 2005 9:48 am |
|
|
right
I have just tested this code
Code: | #include <16F877.h>
#use delay(clock=4000000)
#fuses NOWDT,XT, NOPUT, NOPROTECT, NOLVP
int sensorValue =0x00;
main(void)
{
set_tris_d(0xFF);
set_tris_e(0x00);
disable_interrupts(global);
SETUP_ADC_PORTS(no_analogs);
while(1)
{
sensorValue = input_d();
delay_cycles(1);
output_e(sensorValue);
delay_cycles(1);
}
}
|
And it is the sensorValue variable that is causing the trouble. The input_d() isn't always reading the sensorValue right or there is something happening within the chip screwing it up, but i cant think what! I mean look at the code, thats it in its entirety - so WHY is it screwing up? What am i missing? surely we can thave 3 busted chips?! |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Mar 16, 2005 10:21 am |
|
|
As told you Hans W, we need to know the hardware details of
the sensors that you mention.
I modiffied a little your code to enable you "to see" if the the sensors are
giving a unstable signal. I assume you have a set of Leds connected in
the output monitoring what is going on, you will see them blinking
accordingly.
Code: |
#include <16F877.h>
#use delay(clock=4000000)
#fuses NOWDT,XT, PUT, NOPROTECT, NOLVP
#zero_ram
#use fast_io(d)
#use fast_io(e)
static int8 sensorValue;
main(void)
{
set_tris_d(0xFF);
set_tris_e(0x00);
disable_interrupts(global);
SETUP_ADC_PORTS(no_analogs);
while(1)
{
sensorValue = input_d();
delay_ms(80);
output_e(sensorValue);
delay_ms(80);
}
}
|
Humberto |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Mar 16, 2005 10:27 am |
|
|
Instead of reading port d and assigning what is read to a variable, why not double or even triple-check the portd reading?
What you're doing:
variable = input_d();
What I'd do:
Code: |
no_match = TRUE;
while (no_match) {
variable = input_d();
delay_ms(15); // wait
old_variable = variable;
variable = input_d();
if (variable == old_variable) {
no_match = FALSE;
}
} |
Once this runs you can be reasonable sure that there isn't any input "bounce". Give it a shot and see what happens. |
|
|
Guest
|
|
Posted: Wed Mar 16, 2005 11:31 am |
|
|
sensorValue=input_d();
did you mask off the bits you do not need before entering the switch? you are only using d0-d2. AND it with 0x07
switch(sensorValue&0x07) |
|
|
_Spudtheimpaler Guest
|
Definately something to try! |
Posted: Wed Mar 16, 2005 11:49 am |
|
|
Hi,
I am not actually using any sensors. The program is designed for sensors, but at present we are jsut using 5v wires to touch the pins.
I am just trying the code newguy gave me
Code: | no_match = TRUE;
while (no_match) {
variable = input_d();
delay_ms(15); // wait
old_variable = variable;
variable = input_d();
if (variable == old_variable) {
no_match = FALSE;
}
} |
To no avail :(
Its still reading the input when i put 5v on the input pins, but still outputting the high values for extended periods.
I'll try and draw a diagram
Quote: |
INPUT | OUTPUT
O O O O O O // all inputs outputs low
O O O O O O // Touch input with 5v
|
|
O X O O X O // Input goes high so output shows high
|
|
O O O O X O // Input goes low by removing the cable
//But output remains high for aprx 6-8 seconds.
|
I haven't yet added #zero_ram
#use fast_io(d)
#use fast_io(e)
because i'm nto sure what they do... what do they do?
I'll keep on posting though i've been on this all day now to no avail, so i'll be going home soon
Cheers
Mitch |
|
|
edit Guest
|
|
Posted: Wed Mar 16, 2005 11:51 am |
|
|
In the "quote" section above the
|
|
was set up for the middle O but the board stripped the leading spaces.
just so you know |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: Definately something to try! |
Posted: Wed Mar 16, 2005 12:29 pm |
|
|
_Spudtheimpaler wrote: |
Its still reading the input when i put 5v on the input pins, but still outputting the high values for extended periods. |
Do you have pull down resistors or do you just assume the input will float low when power is removed. |
|
|
_Spudtheimpaler Guest
|
eeerrrrrrrr...... |
Posted: Wed Mar 16, 2005 2:43 pm |
|
|
I am assuming that when i take off the 5v from the input pins, it reads the pin as 0V... Is there some dissipation issues? does it take some time for the input voltage to leave the pin and are there resistor setups that will make this quicker? I've not been doing pic programming for all that long and whenever we have done it at uni before we are given a pre-fabricated board to test all our stuff on... This project was designed to "make us teach ourselves" and so this would be the infuriatingly simple kind of thing that i could miss... |
|
|
|
|
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
|