|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Delay10KTCYx in C18
Hello everyone I'm back again,
First of I would like to thank all who has helped me out on the recent question, and yet I'm here to bug you guys again... Currently I'm using mplab v7.60 C18 v2.40 I've successfully built VexUserCode.mcw right now I would like to run my robot autonomously I'm under the "user_routines_fast.c" and I was trying to program my robot to go straight for 5 seconds and stop using the Delay10KTCYx function in "delay.h" I tried with the code below, how did I come up with the 5000? my chip is PIC18f8520 and I check the datasheets the Fosc is 40MHz so Delay10KTCYx (5000); // should give me a delay of 10000 x 5000 x 4/40M = 5 seconds and after 5 seconds I want it to stop so I added pwm02=127; pwm03=127; is there something wrong with my code or am I using the Delay10KTCYx wrong? Thank you for your time! Code:
void User_Autonomous_Code(void)
{
/* Initialize all PWMs and Relays when entering Autonomous mode, or else it
will be stuck with the last values mapped from the joysticks. Remember,
even when Disabled it is reading inputs from the Operator Interface.
*/
pwm01 = pwm02 = pwm03 = pwm04 = 127;
pwm05 = pwm06 = pwm07 = pwm08 = 127;
pwm09 = pwm10 = pwm11 = pwm12 = 127;
while (autonomous_mode) /* DO NOT CHANGE! */
{
if (statusflag.NEW_SPI_DATA) /* 18.5ms loop area */
{
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */
/* Add your own code here. */
pwm02=100;
pwm03=155;
Delay10KTCYx(5000);
pwm02=127;
pwm03=127;
printf("%2x : %2x %2x %2x %2x %2x %2x\n",(int)rxdata.rc_receiver_status_byte.allbits,
(int)PWM_in1,(int)PWM_in2,(int)pwm01,(int)pwm02,(int)pwm03,(int)pwm04);
Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
}
}
}
|
|
#2
|
|||
|
|||
|
Re: Delay10KTCYx in C18
Your code is in the middle of a loop that NEEDS to get data every 18.5ms and return back a I'm alive message. If you wait for 5 seconds the master CPU is going to think there is a problem and reset the slave.
What you want to do is count the number of times you've been through the loop and when it's been 5 seconds (5 sec / 18.5 ms) then set the PWM values. autoseconds = autoseconds + 185; If autoseconds > 5000 then pwm = 127. |
|
#3
|
|||||
|
|||||
|
Re: Delay10KTCYx in C18
You've got lots of options we can help you with. Time can be based on counting the number of loops within the 18.5ms loop area or based on a hardware timer.
You can learn about state machines - what we typically use in cases like these. Code:
static int counter=0; //keep track of loops to use as a crude timer - static keeps it around from call to call and isn't necessary if you never leave the subroutine.
static int autostate=1; //keep track of what step we're supposed to be doing
switch (autostate)
{
case 1: // Drive forward
pwm02 = 100;
pwm03 = 155; //motor is reversed
if (counter>54) //1 second (1 sec divided by 18.5ms = 54 loops per second)
{
autostate = 2; // move on to the next step
counter = 0; // reset our timer for the next step
}
case 2: // Turnaround
pwm02 = 100;
pwm03 = 100; //motor is reversed
if (counter>108) //2 seconds
{
autostate = 3;
counter = 0;
}
case 3: // Drive forward (returning now)
pwm02 = 100;
pwm03 = 155; //motor is reversed
if (counter>54) //1 second
{
autostate = 4;
counter = 0;
}
case 4: // Stop - What to do when everything else is done
default: // also what to do if an invalid autostate occurs
pwm02 = pwm03= 127; // Make sure the last thing you do is always stop
}
counter++;
Last edited by Mark McLeod : 04-08-2010 at 13:50. |
|
#4
|
|||
|
|||
|
Re: Delay10KTCYx in C18
I have it to work thank you!!
This is what I did Code:
static int counter=0;
pwm02=100;
pwm03=155;
counter= ++counter ;
if(counter>271){ (5/18.5ms)
pwm02=127;
pwm03=127;
}
Also MARK can you show me how to write the Wait subroutine? I can't thank you guys enough! You've been such great help! Last edited by siaohuang : 04-08-2010 at 15:32. |
|
#5
|
|||||
|
|||||
|
Re: Delay10KTCYx in C18
That looks good.
Yes, I was just showing an elaboration on what Foster told you. Instead of the Case statement you can use If statements like you did. The only way the loop will take longer than 18.5ms is if the code you add takes more than 18.5ms to execute and slows everything down so you don't get to the "if (statusflag.NEW_SPI_DATA)" statement in time. That would take an intense time-consuming internal loop, not the sets and checks you're doing. For a simple Wait just duplicate the structure you already recognize. You want to repeat all the work that routine does, so the system doesn't lockup while you wait. I just dashed this off and haven't checked it, but this is the general idea using what you've already learned. You'd add something like this before User_Autonomous_Code. Code:
void My_Wait(int milliseconds)
{
int elapsedtime=0; // in increments of 18.5ms
int elapsedcount=0; // in units of 18.5ms
while((elapsedtime < milliseconds) & autonomous_mode) // also quit if Auto mode happens to end
{
if (statusflag.NEW_SPI_DATA) /* 18.5ms loop area */
{
elapsedcount++;
elapsedtime = elapsedcount * 185 / 10; //the Vex PIC processor doesn't have floating point
Getdata(&rxdata); // tells us when Auto Mode is over
Putdata(&txdata); // Lets the master controller know we're alive and well
}
}
}
pwm02 = 100; Last edited by Mark McLeod : 04-08-2010 at 20:17. |
|
#6
|
|||
|
|||
|
Re: Delay10KTCYx in C18
I had similar code for when I was doing MPLabs. I had a fancy one that would let you have multiple threads and time a few things at the same time.
Ahhhh the days of rolling your own components, the sweet smell of 1's and 0's . Anyway today the RobotC compiler does all of that for you. It also has tasks that you can spawn off to do specific functions and not wait in the main line. Marks 'case' code is a good example of how we would put state machines together and have them do the heavy lifting of what the robot code needed to do. A little work with Google will get you some good tutorials on state machines. But it looks like you are on the right track of getting your robot to move. |
|
#7
|
|||
|
|||
|
Re: Delay10KTCYx in C18
Thank you so much! Mark and Foster ! I seem to get the idea of controlling the timer , but the 18.5 milisecond loop is really an enigma to me, like, how did they come up with the number 18.5ms (in the code that Mark provided me there is also an if loop and it was also stated /* 18.5ms loop area */ how did you know that?)and how will we know that the code that I've written had exceeded 18.5ms
But anyway right now I've moved on, I'm using the sensors! Using Limit Switch Sensors and Bumper Sensors and here is what I did the first time Code:
static int counter=0;
static int signal=0;
void User_Autonomous_Code(void)
{
/* Initialize all PWMs and Relays when entering Autonomous mode, or else it
will be stuck with the last values mapped from the joysticks. Remember,
even when Disabled it is reading inputs from the Operator Interface.
*/
pwm01 = pwm02 = pwm03 = pwm04 = 127;
pwm05 = pwm06 = pwm07 = pwm08 = 127;
pwm09 = pwm10 = pwm11 = pwm12 = 127;
while (autonomous_mode) /* DO NOT CHANGE! */
{
if (statusflag.NEW_SPI_DATA) /* 18.5ms loop area */
{
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */
/* Add your own code here. */
pwm02=100;
pwm03=155;
counter= ++counter ;
if(counter>541){
pwm02=127;
pwm03=127;
}
signal=Get_Analog_Value(rc_ana_in02);
if (signal!=0){
pwm02=127;
pwm03=127;
}
printf("%2x : %2x %2x %2x %2x %2x %2x\n",(int)rxdata.rc_receiver_status_byte.allbits,
(int)PWM_in1,(int)PWM_in2,(int)pwm01,(int)pwm02,(int)pwm03,(int)pwm04);
Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
}
}
}
Code:
static int counter=0;
static int signal=1;
void User_Autonomous_Code(void)
{
/* Initialize all PWMs and Relays when entering Autonomous mode, or else it
will be stuck with the last values mapped from the joysticks. Remember,
even when Disabled it is reading inputs from the Operator Interface.
*/
pwm01 = pwm02 = pwm03 = pwm04 = 127;
pwm05 = pwm06 = pwm07 = pwm08 = 127;
pwm09 = pwm10 = pwm11 = pwm12 = 127;
while (autonomous_mode) /* DO NOT CHANGE! */
{
if (statusflag.NEW_SPI_DATA) /* 18.5ms loop area */
{
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */
/* Add your own code here. */
pwm02=100;
pwm03=155;
counter= ++counter ;
if(counter>541){
pwm02=127;
pwm03=127;
}
signal=Get_Analog_Value(rc_ana_in02);
if (signal=0){
pwm02=127;
pwm03=127;
}
printf("%2x : %2x %2x %2x %2x %2x %2x\n",(int)rxdata.rc_receiver_status_byte.allbits,
(int)PWM_in1,(int)PWM_in2,(int)pwm01,(int)pwm02,(int)pwm03,(int)pwm04);
Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
}
}
}
I've been growing so dependent on you guys...Thank you so much for your help... Last edited by siaohuang : 06-08-2010 at 15:49. Reason: the code wrapping didn't come out |
|
#8
|
|||
|
|||
|
Re: Delay10KTCYx in C18
The problem is that the buttons go from approximately 0 to ~255 and it's the approximate part that is the issue.
Try: Code:
if (signal < 20){
pwm02=127;
pwm03=127;
}
Code:
if (signal > 235){
pwm02=127;
pwm03=127;
}
The 18.5 ms has to do with how long it takes the control signals from the transmitter to get to the master CPU. The signals from the transmitters are PWM with a fixed length channel. On my wiki there is the following note that I've copied from someone named Tinkerman. Quote:
http://www.vexfan.com/viewtopic.php?t=227 Last edited by Foster : 06-08-2010 at 16:14. Reason: Add links to the orginal article |
|
#9
|
|||||
|
|||||
|
Re: Delay10KTCYx in C18
In addition to what Foster covered...
if statement comparisons need double equal signs (==). A single equal sign doesn't compare, it changes the value. So if (signal=0)changes the value of signal to zero, then evaluates if(0)which will always be False. The correct way is: if (signal==0) {The 18.5ms is more of a design choice for how often transmission packets are sent. Through the years FIRST has had some variation in packet rates, for instance, the predecessor of the Vex controller used a packet rate of 17ms, and the larger version used for FRC at that time had a rate of 26.2ms. Whenever you use something like this as a crude timer you'll have to investigate and determine what transmission rate was used. Last edited by Mark McLeod : 06-08-2010 at 16:31. |
|
#10
|
|||
|
|||
|
Re: Delay10KTCYx in C18
Thank you guys so much! I have it working!! After reading I did some adjustments and it worked just as I wanted: When the button is pressed the robot will reverse and make a turn and go straight. Here is my code for that!
Code:
static int counter2=0;
static int counter3=0;
static int signal=1;
static int trigger=0;
pwm02=100;
pwm03=155;
signal=Get_Analog_Value(rc_ana_in02);
if (signal==0){
trigger=1;
}
if(trigger==1){
pwm02=155;
pwm03=100;
counter2=++counter2;
if (counter2>109){
pwm02=155;
pwm03=155;
counter3=++counter3;
if (counter3>109){
pwm02=155;
pwm03=100;
trigger=0;
counter2=0;
counter3=0;
}
}
}
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Trig functions in C18 3.10 | dmlawrence | Programming | 9 | 08-02-2008 09:33 |
| MPLab 7.20/C18 2.40 | Andy L | Programming | 2 | 07-04-2007 20:11 |
| C18 v. 2.4 | wingnut1705 | Programming | 2 | 05-02-2007 15:52 |
| C18 v2.4 | CircularLogic | FIRST Tech Challenge | 2 | 16-07-2006 15:20 |
| Linux C18 compiler? | Servo888 | Robotics Education and Curriculum | 1 | 13-12-2003 01:27 |