Hello everybody. I’m programming a “metal detector” on my robot so it can sense a small piece of aluminum tape that will be on a rope. The rope will go up and down (our version of an arm) and there will be (we haven’t decided yet) appx. 4 pieces of tape on the rope. So, when the tape passes the sensor, I want the program to keep track so when it reaches a certain height it will automatically stop, so we dont have to manually stop the arm. So from the first four passes of the tape through the sensor, the rope will be moving up, and the next four (five to eight) will let us know that the rope is going down. Will this work? And is where in the code I’m placing this correct (in user_routines_fast.c Process_Data_From_Local_IO)? (I want to use the relay2 lights so I can see whether I’m going UP or going DOWN. at full up they are both on and at full down they are both off. red is going down and green is going up.)
void Process_Data_From_Local_IO(void)
{
int count = 0;
if(digital_io_04 == 1) //If sensor, which connects to Dig In/Out port 4, goes on...
{
count++; //Number of times tape passes through the sensor.
Switch01_LED = 1; //Switch01 goes on when the tape passes the sensor.
}
else
{
Switch01_LED = 0;
}
if(count == 8)
{
Relay2_green = 0;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it retreats to ground level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
count = 0;
}
else if(count == 7)
{
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 1st level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
}
else if(count == 6)
{
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 2nd level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
}
else if(count == 5)
{
Relay2_green = 0;
Relay2_red = 1;
//pwm03 does not equal 127 because it must pass the tape in order to go beneath the top level.
}
else if(count == 4)
{
Relay2_green = 1;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it reaches top level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
}
else if(count == 3)
{
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 2nd level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
}
else if(count == 2)
{
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 1st level.
//pwm03 = p3_y; //re-maps pwm03 to joystick
}
//if count == 1 then that just means that it passed through the first piece of tape which will be used to show that it is in full DOWN position.
/* Add code here that you want to be executed every program loop. */
}
So, First of all, if you noticed I put “//pwm03 = p3_y” in comments. This is because I’m not sure if I give pwm03 a number (127), if it will permenantly make it that number? So would I have to re-map it to the joystick? or would it do that automatically in the Default_Routine()? Also, does the first line of code with the sensor make sense? And I’m not sure if I put this code in the correct spot in the program. I’m sort of new to programming, just started late last year. Thanks in advance for your help!
the first thing I would be weary about is the aluminum tape and the sensor. cause if its a magnetic sensor of any sort it wont work(aluminum is non-ferris at room temp)
as far as your code goes.
instead of counting when ever your on the tape or not youll want to count when ever you wernt on the tape and now are(I would suggest a now last variable set up, as in at the top of your code you say now = last; digital_io_04 = now;then for your if you say if (now == 1 && last ==0). otherwise youll get many counts for the same strip of tape.
youll also want to track what direction the motor is turning because if you change direction in the middle of the string youll be on tape 2 and have a count of for. for that I would do an if else for incrementing/decrementing the count based on if the pwm is > or < 127)
also for just style points you might want to but all those if elses in a switch statement.
To clarify, this is a continuous loop of rope and you’re only ever running the motor in one direction, correct? There’s a few problems in your code. It will compile, but probably won’t do what you think. I can’t comment on whether it will work in your application cause I can’t quite decipher what your apparatus is doing. Here’s what I’ve noticed:
You mean rc_dig_in04, NOT, digital_io_04. You use digital_io_04 to define port 4 as an output or input. once you’ve defined it as an input, you read its value from rc_dig_in04.
I think you’re going to want to wrap your entire bit of code there in an if(pwm03 != 127) statement. If you don’t, your code will be counting up as long as rc_dig_in04 is 1. Even if the motor isn’t running and just sitting there.
I don’t think you want this in Process_Data_From_Local_IO. Unless you’re pretty certain about the output of the sensor, you might have to deal with a “bouncing” issue where the input value bounces between 0 and 1 as the sensor decides whether it sees something or not. Process_Data_From_Local_IO loops fast enough that it might get confused. Aside from which, changing the pwm03 value won’t have any effect until the next time your Default_Routine runs anyways, so I’d put all of this in there.
After you set pwm03 to 127, the tape is still sitting in the sensor, and the sensor is still reading 1. So when you start up the motor again, the sensor will still say 1, and you’ll instantly stop. You should add in code that waits until rc_dig_in04 goes back to 0 before you start checking for it to be 1 again.
Finally, your giant if-else chain for count is really tailor made for for a switch-case statement. You might want to change it to that to simplify your code a bit.
Ok. I understand what you mean by changing it to a switch statement, but unfortunately I JUST learned what they were about 2 weeks ago in AP computer science A in school. So, I’ve had little experience working with them. How might I change this into a switch statement?
Also, I would actually be running this motor in 2 directions. The first direction (forward) would draw back the rope and lift up the forklift. Position 1 is the ground position, 2 is the 1st layer on the spider, 3 is the 2nd layer on the spider, and 4 is the 3rd (highest layer) on the spider. Then it would need to come back down.
So let’s say I kept the code as is, but added the if(pwm03 != 127) over the entire thing, both the if(rc_dig_in04 == 1) and the if(count == 8)…then could that also satisfy this?
After you set pwm03 to 127, the tape is still sitting in the sensor, and the sensor is still reading 1. So when you start up the motor again, the sensor will still say 1, and you’ll instantly stop. You should add in code that waits until rc_dig_in04 goes back to 0 before you start checking for it to be 1 again.
Also, I agree with changing rc_dig_in04 (previously digital_io_04) to the now last variable set up that you suggested. (I’m kind of talking to both of you now).
switch(count)
{
case 1:
//all your if count == 1 here
break;// never ever ever forget to put this . .ever
case 2:
//all your if count == 2 here
break; //EVER
case 3:
.
.
.
.
.
case 8:
//blah
break;
}
also for bidirectional I would have something like this before incrementing the count
if(pwm13 >= 127)
count++;
else
count–;
also when you stop the motor and “remap it” to the joy . .you wont see a stop. it will set pwm13 to 127 then set it to what ever the joy is at when it stopped in the next line. so youll have to figure a way to pause it for a sec(I would suggest using 2 digital buttons one for step up a notch and one for step down . .and some way of overriding)
void Default_Routine(void)
{
int count = 0;
int now;
int last;
now = last;
rc_dig_in04 = now;
blah blah blah…map joysticks…
/***************
* Sensor Code *
***************/
if((pwm03 < 125) || (pwm03 > 129))
{
if((now == 1) && (last == 0)) //If sensor, which connects to Dig In/Out port 4, goes off...
{
count++; //Number of times tape passes through the sensor.
Switch1_LED = 1; //Switch01 goes on when the tape passes the sensor.
}
else
{
Switch1_LED = 0;
}
if(count == 8)
{
Relay2_green = 0;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it retreats to ground level.
count = 0;
}
else if(count == 7)
{
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 1st level.
}
else if(count == 6)
{
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 2nd level.
}
else if(count == 5)
{
Relay2_green = 0;
Relay2_red = 1;
//pwm03 does not equal 127 because it must pass the tape in order to go beneath the top level.
}
else if(count == 4)
{
Relay2_green = 1;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it reaches top level.
}
else if(count == 3)
{
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 2nd level.
}
else if(count == 2)
{
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 1st level.
}
//if count == 1 then that just means that it passed through the first piece of tape which will be used to show that it is in full DOWN position.
}
So I have yet to make the switch statement, but I made some changes. Do you understand yet what I am trying to do with the forklift Kevin? (Any other thoughts also) Thank you guys so much. You’re saving my team of 5.
switch(count)
{
case 2:
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 1st level.
break;
case 3:
Relay2_green = 1;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it reaches 2nd level.
break;
case 4:
Relay2_green = 1;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it reaches top level.
break;
case 5:
Relay2_green = 0;
Relay2_red = 1;
//pwm03 does not equal 127 because it must pass the tape in order to go beneath the top level.
break;
case 6:
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 2nd level.
break;
case 7:
Relay2_green = 0;
Relay2_red = 1;
pwm03 = 127; //Motor stops when it retreats to 1st level.
break;
case 8:
Relay2_green = 0;
Relay2_red = 0;
pwm03 = 127; //Motor stops when it retreats to ground level.
count = 0;
break;
//if count == 1 then that just means that it passed through the first piece of tape which will be used to show that it is in full DOWN position.
}
Aight, so this is my switch.
Now, if I try to do the forwards/backwards thing, I wont have the correct relay lights, but I guess that would be ok. We could do without that. Also, I had a feeling that I would have a problem with the joysticks and setting the pwm value to 127. Could I use a timer? We’ll see, thats another step for another day. THANKS AGAIN SO MUCH!!!
Please note that the use of metallic tape on the rope is not specifically allowed by <R35>. Although most inspectors may not question this implementation, you run the risk of being told to change it at your competition unless you get clarification first.
I suggest that you post as to the legality of this type of sensor tape on the FIRST Q&A forum to avoid problems later.
I will certainly check that out. (I hadn’t signed up on that website yet, so I’m waiting for my activation now). If that isn’t allowed, do you think I could use a staple?
And, how can I make the motor stop at each level? I don’t think
pwm03 = 127;
will work because it will just turn it off for a split second and by then my joystick would not have gotten back to 127, so it’d keep going, I think. A timer (never used one before)? Or, another solution? Anything I can do to make the winch stop at each level would be greatly appreciated.
Does this bug anyone else? I think that the line that says “rc_dig_in04 = now;” should say “now = rc_dig_in04;”, and the line that says “now = last;” should say “last = now;”. Normally, you don’t set the sensor value variable.
Thanks, I see that now. But how do I stop the pwm03 motor? it wont just stop even though i set it to 127, because the next loop it is remapped to the joystick, so theres not enough time for me to let the joystick go back to 127 itself.
Define a static variable to be used as a “time to stop” flag. Whenever you detect the tape (or whatever you use to tell when you’re at the right level), set the flag. Whenever the joystick reads 127 (or close enough), clear the flag. If the flag is set, stop the motor. If the flag is clear, copy the joystick value to the motor.
Hi, I’ve posted some of this a few times, but I think I might be able to get it to work now. I’m using a winch system for my forklift and I’ll be using a metal sensor and 4 pieces of metallic tape on the rope for the winch to let the program know what level the forklift is on. 1st level being the ground level, and 4th level being the highest level on the rack. I was having a problem with turning the motor off at each level, but now I think i might have solved it. Any help would be appreciated ENORMOUSLY!
Code:
void Default_Routine(void)
{
int count = 0;
int now; //for mapping rc_dig_in04 to ON or OFF (sensor)
int last; //for mapping rc_dig_in04 to ON or OFF (sensor)
int now2; //for mapping p3_sw_trig to ON or OFF (reset p3_y)
int last2; //for mapping p3_sw_trig to ON or OFF (reset p3_y)
int now3; //for mapping p3_sw_aux1 to ON or OFF (reset counter)
int last3; //for mapping p3_sw_aux1 to ON or OFF (reset counter)
now = last;
rc_dig_in04 = now;
last2 = now2;
now2 = p3_sw_trig;
last3 = now3;
now3 = p3_sw_aux1;then some joysticks are mapped (pwms..)
if((now3 == 1) && (last3 == 0)) //p3_sw_aux1 sets counter to 0 in case forklift needs to be reset.
{
count = 0;
}
if((now2 == 1) && (last2 == 0)) //p3_sw_trig sets joystick 3 y-axis to forklift motor.
{
pwm03 = p3_y;
}
if(( pwm03 < 125) || (pwm03 > 129)) //if py_3 is being used
{
if((now == 1) && (last == 0)) //If sensor, which connects to Dig In/Out port 4, sends a signal...
{
count++; //Number of times tape passes through the sensor.
Switch1_LED = 1; //Switch01 goes on when the tape passes the sensor.
}
else
{
Switch1_LED = 0;
}
switch(count)
{
case 1: //if count == 1 then that just means that it passed through the first piece of tape which will be used to show that it is in full DOWN position.
Relay2_green = 1;
Relay2_red = 0;
break;
case 2:
Relay2_green = 1;
Relay2_red = 0;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it reaches 1st level of rack.
break;
case 3:
Relay2_green = 1;
Relay2_red = 0;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it reaches 2nd level.
break;
case 4:
Relay2_green = 1;
Relay2_red = 1;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it reaches top level.
break;
case 5:
Relay2_green = 0;
Relay2_red = 1;
//pwm03 does not equal 127 because it must pass the tape in order to go beneath the top level.
break;
case 6:
Relay2_green = 0;
Relay2_red = 1;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it retreats to 2nd level.
break;
case 7:
Relay2_green = 0;
Relay2_red = 1;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it retreats to 1st level.
break;
case 8:
Relay2_green = 0;
Relay2_red = 0;
pwm03 != p3_y;
pwm03 = 127; //Motor stops when it retreats to ground level.
count = 0;
break;
}
}You think it will work? If the sensor senses the metal, the motor will stop because it no longer is mapped to the joystick. Then if I want to keep going, I press the p3trigger button and pwm03 is remapped to the joystick because of an if statement. By the way, the relay lights just mean that if its going up, the green light is on. if its going down the red light is on. if its at the top, they are both on. Also, there are some safety measures with this, as in, since the counter counts each time the tape passes through the sensor, it must go up the whole way and down the whole way, it cannot go up to one level, then down a level, then up two...the counter will get all messy cabooy, and i haven't had the time to figure out the code for that (i would have to include the direction of the y-axis and it'd get complicated..im new at this so imma keep this as simple as possible). So, if the driver accidentally goes down when he was supposed to go up, he would go all the way down to the bottom and then press p3_sw_aux1 which would reset the counter. Tell me if you understand any of this and let me know if you think any of this would work. I could really use the confidence.