Go Down

Topic: how to enhance this  code? (Read 443 times) previous topic - next topic

psthandier

Mar 23, 2008, 04:27 pm Last Edit: Mar 23, 2008, 04:41 pm by psthandier Reason: 1
Hi there!

Ive been working on a arduino based robot it has wireless comunications servos and h bridge and 2 dc motors, the mecanical part is quite done and te code im posting below is able to test all the motion and comunication stuff, now my new problem is that as mi code is very basic it cant make more than one action at a time ex i cant move eyes and mouth at the same time or move forward and blink the way my code is made is so basic it has to wait for one condition to finish to pass to another


how can i skip this linear wayof working of the code?
working with functions can do this?

i dont need th hole solution but some hints to develop for some kind of multitasking

Thanks a lot!

 

#include <SoftwareSerial.h>;

#define rxPin 2
#define txPin 1



char prevChar = 0;
int i = 0;

int a = 0;
SoftwareSerial rfSerial =  SoftwareSerial(rxPin, txPin);

void setup(){
 
 pinMode(rxPin, INPUT);
 pinMode(13, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(8, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(5, OUTPUT);
 pinMode(4, OUTPUT);
 pinMode(3, OUTPUT);

 rfSerial.begin(2400); // begin serial connection with RF Link unit
 Serial.begin(2400); // begin serial communication over USB to the computer
  digitalWrite(13, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(3, HIGH);
}

void loop(){
 
 
 
   
 byte someChar = 0;  
 someChar = rfSerial.read(); // read whatever the RF Link has to offer

 if(someChar==45){
   //move bot forward with h bridge

   digitalWrite(12, HIGH);
   digitalWrite(9, HIGH);
   digitalWrite(11, LOW);
   digitalWrite(10, HIGH);
   digitalWrite(8, HIGH);
   digitalWrite(7, LOW);
   delay(200);
}


 if(someChar==54){
   //move bot backwards
   digitalWrite(12, HIGH);
   digitalWrite(9, HIGH);
   digitalWrite(11, HIGH);
   digitalWrite(10, LOW);
   digitalWrite(8, LOW);
   digitalWrite(7, HIGH);
   delay(200);
}



 if(someChar==73){
   //move bot to the right
   digitalWrite(12, HIGH);
   digitalWrite(9, HIGH);
   digitalWrite(11, HIGH);
   digitalWrite(10, LOW);
   digitalWrite(8, HIGH);
   digitalWrite(7, LOW);
   delay(200);
}



 if(someChar==77){
   //move bot to the left
   digitalWrite(12, HIGH);
   digitalWrite(9, HIGH);
   digitalWrite(11, LOW);
   digitalWrite(10, HIGH);
   digitalWrite(8, LOW);
   digitalWrite(7, HIGH);
   delay(200);  
 }


 if(someChar==34){
   // blink eyes
   for(i=0;i<20;i++){
     
     
    digitalWrite(6, HIGH);
    delayMicroseconds(850);
    digitalWrite(6, LOW);
    delay(20);  
 }
   delay(50);

for(i=0;i<20;i++){
    digitalWrite(6, HIGH);
    delayMicroseconds(300);
    digitalWrite(6, LOW);
    delay(20);
   }
   delay(50);
 }

 if(someChar==43){
   //open close mouth
   for(i=0;i<20;i++){
     
     
    digitalWrite(5, HIGH);
    delayMicroseconds(750);  
    digitalWrite(5, LOW);  
    delay(20);
   }
   delay(50);


   for(i=0;i<20;i++){
    digitalWrite(5, HIGH);  
    delayMicroseconds(550);
    digitalWrite(5, LOW);  
    delay(20);
   }
   delay(50);
 }


// digitalWrite(12,LOW);
 digitalWrite(11,LOW);
 digitalWrite(10,LOW);
 digitalWrite(9,LOW);
 digitalWrite(8,LOW);
 digitalWrite(7,LOW);
 Serial.println(someChar,DEC);

}

Triffid Hunter

Try something like this:

enum
{
forward_action
backward_action
stop_action
rolleyes_action
} action_enum;

uint16_t actions;

void forward()
{
 setMotor(mLeft, 255);
 setMotor(mRight, 255); // or whatever you do to go forwards
 actions &= ~forward_action; // we're going forwards now, don't need to come back to this function
}

void backward()
{
 setMotor(mLeft, 0);
 setMotor(mRight, 0); // or whatever you do to go backwards
 actions &= ~backward_action; // we're going backwards now, don't need to come back
}

void stop()
{
 setMotor(mLeft, 128);
 setMotor(mRight, 128); // or whatever you do to stop
 actions &= ~(forward_action | backward_action | stop_action); // make sure we kill all movement commands
}

void rolleyes()
{
 setMotor(mEyes, 255);     // or however you do this in your robot
 if (digitalInput(inEyesHome))  // detect when eyes have returned to start point
   actions &= ~rolleyes_action; // and only then disable this action, otherwise we do it again every loop
}

void main()
{
 setup();  // this does all your I/O and serial and whatever else setup

 for (;;)
 {
   /*
     these functions should never wait for anything. If you have to wait for something, simply don't make it disable itself until that thing has happened. They'll be called tens of thousands of times per second, so don't worry too much about missing things.
     in fact, nothing in this loop should ever wait. don't even use delay(). If you want to delay, count a variable down every time your function is called, do something when it reaches zero. Alternatively, use the clock that the timers use, or even a whole timer.
     the less time it takes each function to sort itself out, the faster they'll be called. fast is good.
   */
   if (actions & (1<<forward_action)) forward();
   if (actions & (1<<backward_action)) backward();
   if (actions & (1<<stop_action)) stop();
   if (actions & (1<<rolleyes_action)) rolleyes();

   if (rfSerial.canread())  // critically important that we never sit and wait - the loop *must* keep looping or actions won't be able to stop themselves when they want to
   {
     switch (rfSerial.read())
     {
       case 'F':
         actions |= forward_action; break;
       case 'B':
         actions |= backward_action; break;
       case 'S':
         actions |= stop_action; break;
       case 'R':
         actions |= rolleyes_action; break;
     }
   }
 }
}


note that the above needs *lots* of filling in and adapting to your needs, also you can't have more than 16 actions unless you add another variable. It's purely a demonstration of what you're probably heading towards anyway.

Note that if you want sequences, all you have to do is make one action enable the next one before disabling itself

If you want to abstract this into a reusable code block, you'll want to define a struct act { uint8_t enabled; void (*func)(struct act *); }; then a struct act actarray[MAXACTIONS]; then initialise all the fuction pointers to 0 so you know which actions aren't in use. set enabled to 1 to start the action, set it to a larger nonzero number if you want timed stuff then decrement it within the action function itself. pass the function a pointer to it's struct action so it can change its own enable state. Then, just for (;;) { for (i=MAXACTIONS-1;i;i--) actarray.enabled && actarray.func(&actarray); enableActionsHere(); }

Go Up