Go Down

Topic: Speed up arduino (Read 6 times) previous topic - next topic

AWOL

Code: [Select]
fsrConductance = 1000000;           // we measure in micromhos so
    fsrConductance = fsrResistance;

I suppose you can hope the compiler optimises-out pointless assignments.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

hong89

Code: [Select]

int A,B,C ;
int fsrPin = 0;     // the FSR and 10K pulldown are connected to a0
int fsrReading;     // the analog reading from the FSR resistor divider
int fsrVoltage;     // the analog reading converted to voltage
unsigned long fsrResistance;  // The voltage converted to resistance, can be very big so make "long"
unsigned long fsrConductance;
long fsrForce;       // Finally, the resistance converted to force
int count = 0;      //count of position
double Force_corr, Pos_corr;
int Status_out, enable, Regler_Start, Init_Start, corr_Start, Auto_Status;
int Enable;        //emergency stop

double SettingValue, PosGain;
double x, Sampletime,v, w;
double SatForce;

int V1;
double Freq;

double clock;

int state = HIGH;




void setup()
{
  Serial.begin(9600);
  Status_out = enable = Regler_Start = Init_Start = corr_Start = Auto_Status = 0 ;
  Enable = 1;
  attachInterrupt(4, emergency, RISING);   //interupt 4 , digital pin 19
   state = HIGH;


}


void loop()
{
 
// analogRead(1);
digitalWrite (10, state);


  Position_Count();
  Force();
  Flow_Control(2);
 

  Correction(fsrForce, count, corr_Start);

 
  if (Regler_Start == 0)
  {
    int f = 0-10*25;
    Pos_SetValue(353.81,3.8095,22.8571);
   
    Force_SetValue(f);
    Potential();
    Virtual_System(0.099048,0.2,0,-0.04,150);
  }
  else
  {
   
  }
 
   state =!state;
}


void Position_Count()
{
  int p=0;
  int a1 = 0;
  int b1 = 0;
 
  A = digitalRead(22);
  B = digitalRead(24);

  if(A==1 && a1!=A)
  {
     if(B==1)
     {
       p=p-1;
       a1=1;
       b1=1;
     }
     count=p;
   }
   
   if(A==1 && a1!=A)
   {
      if(B==0)
      {
        p=p+1;
        a1=1;
        b1=0;
      }
      count=p;
   }

   if(A==0 && a1!=A)
   {
      if(B==1)
      {
        p=p+1;
        a1=0;
        b1=1;
      }
      count=p;
   }

   if(A==0 && a1!=A)
   {
      if(B==0)
      {
        p=p-1;
        a1=0;
        b1=0;
      }       
      count=p;
   }

   if(B==1 && b1!=B)
   {
      if(A==1)
      {
        p=p+1;
        b1=1;
        a1=1;
      }
      count=p;
   }
   
   if(B==1 && b1!=B)
   {
      if(A==0)
      {
        p=p-1;
        b1=1;
        a1=0;
      }
      count=p;
   }

   if(B==0 && b1!=B)
   {
      if(A==1)
      {
        p=p-1;
        b1=0;
        a1=1;
      }
      count=p;
   }
   
   if(B==0 && b1!=B)
   {
      if(A==0)
      {
        p=p+1;
        b1=0;
        a1=0;
      }
      count=p;
   }

}


void Force()
{
   fsrReading = analogRead(fsrPin);

  // analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
//  fsrVoltage = map(fsrReading, 0, 1023, 0, 5000);
 
  fsrVoltage = fsrReading*5;
 


 
    // The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
    // so FSR = ((Vcc - V) * R) / V        yay math!
    fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
    fsrResistance *= 10000;                // 10K resistor
    fsrResistance /= fsrVoltage;

    fsrConductance = 1000000;           // we measure in micromhos so
    fsrConductance /= fsrResistance;

    // Use the two FSR guide graphs to approximate the force
    if (fsrConductance <= 100)                  //range 0-2N
    {
      fsrForce = fsrConductance /20;
//      Serial.print("Force in Newtons: ");
//      Serial.println(fsrForce);     
    }
   
    else
    {
      fsrForce = fsrConductance /50;                //range 80N-100N
//      fsrForce /= 50;           
    }
   
   
 
  fsrForce = fsrForce*3;
}

void Force2()
{
   fsrReading = analogRead(1);

  // analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
// fsrVoltage = map(fsrReading, 0, 1023, 0, 5000);
 
  fsrVoltage = fsrReading*5;
 


 
    // The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
    // so FSR = ((Vcc - V) * R) / V        yay math!
    fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
    fsrResistance *= 10000;                // 10K resistor
    fsrResistance /= fsrVoltage;

    fsrConductance = 1000000;           // we measure in micromhos so
    fsrConductance /= fsrResistance;

    // Use the two FSR guide graphs to approximate the force
    if (fsrConductance <= 100)                  //range 0-2N
    {
      fsrForce = fsrConductance /20;
//      Serial.print("Force in Newtons: ");
//      Serial.println(fsrForce);     
    }
   
    else
    {
      fsrForce = fsrConductance /50;                //range 80N-100N
//      fsrForce /= 50;           
    }
   
   
 
  fsrForce = fsrForce*3;
}

void Correction(double Force, double Position, int Reset)

  int mtime = 0;
  int force = 0;
  int pos = 0;
  int mreset = 0;


 
  if(Reset==1 && mreset==0)
  {
    if(mtime==0)
    {
        mtime = clock;
    }
    if(mtime >= 0)
    {
        if(clock>(mtime + 5))
        {
            force = Force;
            pos = Position;
            mreset = 1;
        }
    }
  }
  if(Reset==0)
  {
    mreset=0;
    mtime=0;
  }
  Force_corr = force; 
  Pos_corr = pos;

}


void Flow_Control(int Status)
{
// int Status_out, enable, Regler_Start, Init_Start, corr_Start, Auto_Status;
//   Status_out = enable = Regler_Start = Init_Start = corr_Start = Auto_Status = 0;
 
 
  Status_out=Status;    //Status = input,   Status_out = output
  if(Enable==1)         //Enable = input,   enable = output
  {
    if(Status==0)
    {
        enable=0;
    }
   
    if(Status==1)
    {
        enable=4.5;
        Init_Start = 1;
    }
    else
    {
        Init_Start = 0;
    }
   
    if(Status==2)
    {
        enable=0;
        corr_Start=1;
    }
    else
    {
        corr_Start=0;
    }             
   
    if(Status==3)
    {
        enable=4.5;
        Regler_Start=1;
    }
    else
    {
        Regler_Start=0;
    }
  }
  if(Enable==0)
  {
    enable==0;
    Regler_Start=0;
    corr_Start=0;
    Auto_Status=0;
  }
}


void emergency()
{
  Enable = 0;
}


// Pos_SetValue(353.81, 3.8095, 22.8571 )
void Pos_SetValue(double P_Person, double I_Gain, double D_Gain)
{
  double istPosition ;
  double SetValue;
  double PosDiff;
  int Position;
 
  Position = count - Pos_corr;
 
  istPosition = Position *0.007;
  PosDiff = x - Position;

  double intPosDiff;
 
  //intPosDiff ---> integration of PosDiff 
  intPosDiff += PosDiff*Sampletime;
 
 
  SetValue = v*w*D_Gain + PosDiff*P_Person +I_Gain*intPosDiff;
 
 
  // SettingValue ---> go through saturation function
  if(SetValue >= 10)
  {
    SettingValue = 10;
  }
 
  else if(SetValue <= -10)
  {
    SettingValue = -10;
  }
 
  else
  {
    SettingValue = SetValue;   // Output Setting Value to control motor
  } 
   
  PosGain = SetValue - SettingValue; 
 
}

/////////  Force_SetValue( -10*25 / -5*15, )
void Force_SetValue(int Ks)
{
  int Force;
  double SetForce;
 
  Force = fsrForce - Force_corr;
 
  SetForce = x*Ks -23*Force; 
 
  // SatForce --> SetForce go through saturation 
 
  if(SetForce >= 50)
  {
    SatForce = 50;
  }
 
  else if(SetForce <= -50)
  {
    SatForce = -50;
  }
 
  else
  {
    SatForce = SetForce;   // Output Setting Value to control motor
  }
}


/////////////////// Virtual_System(0.099048, 0.2, ??, -0.04, 150)
void Virtual_System(double maxampl, double SollAmpl, double Kp, double Damp, int Mass )
{
  double Amplitude, P_ampl;
  double Sum;
  double dampingValue, Damping;
  double Vset;
  double acceleration, acceleration2;
 
  Amplitude = sqrt(v*v + x*x);
 
  // C code for dampingValue, if...else
  if(Amplitude >= maxampl && Amplitude <= maxampl+0.05)
  {
    dampingValue = 0.1*Vset;
  }
  else if(Amplitude > maxampl+0.05)
  {
    dampingValue = 0.3*Vset;
  }
  else if(Amplitude > maxampl+0.1)
  {
    dampingValue = 10*Vset;
  }
  else
  {
    dampingValue = 0;
  }
 
  P_ampl = Amplitude - SollAmpl;
 
  Damping = P_ampl*Kp; 
 
  Sum = Vset*Damping; 
 
  acceleration = 0 - dampingValue - Sum - Vset*Damp - x*w - SatForce/Mass;
 
  double V_Conversion;
 
  if(v >= 0)
  {
   V_Conversion = 1 / ((1+V1)*(1+V1)) ;
  }
  else
  {
    V_Conversion = 1 / ((1-V1)*(1-V1)) ;
  }
 
  acceleration2 = acceleration*V_Conversion;
 
  // v = integrate of acceleration2
  v = v + acceleration2; 
 
  Potential(); 
  w = Freq * 2*PI/60 ;

   Vset = v*w - PosGain; 
 
  //x = integrate of Vset   
  x = x + Vset*Sampletime ;
 
}

void Potential()
{
  int PotentioPin = 2;     
  int PotentioReading;   
  int Potentiometer;

  PotentioReading = analogRead(PotentioPin); 

  // Potentiometer reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
//  Potentiometer = map(PotentioReading, 0, 934, -2500, 2500);
 
  Potentiometer = PotentioReading * 5;
 
  double U;
  U = Potentiometer;

  if (PotentioReading != 0 )
    {
      Freq = floor((8+3*U)*4+0.5)/4;
    }
  else
    {
      Freq = 1;
    } 
}

PaulS

#17
Apr 16, 2012, 12:21 pm Last Edit: Apr 16, 2012, 12:23 pm by PaulS Reason: 1
Code: [Select]
 Status_out = enable = Regler_Start = Init_Start = corr_Start = Auto_Status = 0 ;
 Enable = 1;

It's generally not a good thing to use variables that differ only in case. When I see that, I usually quit reading.

Code: [Select]
        enable=4.5;
enable is an int!

AWOL

Code: [Select]
Status_out = enable = Regler_Start = Init_Start = corr_Start = Auto_Status = 0 ;
Don't you trust the compiler to have done this for you?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

hong89


Code: [Select]
Status_out = enable = Regler_Start = Init_Start = corr_Start = Auto_Status = 0 ;
Don't you trust the compiler to have done this for you?


I think this not the reason make my system slow right?

AWOL

Correct.
But since I didn't see any code to help you/us analyse the speed of the code, I thought I'd just add that comment.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon


I check the sampling rate by setting high and low at one of the digital pin and monitor with scopemeter.


Oh? I don't see that part. Nor do I see any data declarations.

Look, if it takes a week or two to get any code out of you we will get bored. This is the Programming Questions section. You are supposed to post code, and ask questions about it. Not just "I have some code ... why doesn't it work?".
http://www.gammon.com.au/electronics

Nick Gammon

Code: [Select]
digitalWrite (10, state);

Where do you set pin 10 to be output?

Where do you set pin 10 low again? What does that line achieve?

Code: [Select]
  A = digitalRead(22);
  B = digitalRead(24);

  if(A==1 && a1!=A)
  {
     if(B==1)
     {
       p=p-1;
       a1=1;
       b1=1;
     }
     count=p;
   }
   
   if(A==1 && a1!=A)
   {
      if(B==0)
      {
        p=p+1;
        a1=1;
        b1=0;
      }
      count=p;
   }

   if(A==0 && a1!=A)
   {
      if(B==1)
      {
        p=p+1;
        a1=0;
        b1=1;
      }
      count=p;
   }

   if(A==0 && a1!=A)
   {
      if(B==0)
      {
        p=p-1;
        a1=0;
        b1=0;
      }       
      count=p;
   }


This is just nonsense. What about proper data names? How about comments?

Quote
I check the sampling rate by setting high and low at one of the digital pin and monitor with scopemeter.


I still don't see where you are doing that.
http://www.gammon.com.au/electronics

hong89

I do it in the loop toggle after finished each loop.

Code: [Select]

void loop()
{
 
// analogRead(1);
digitalWrite (10, state);    //here the code set digital pin 10 to high


  Position_Count();
  Force();
  Flow_Control(2);
 

  Correction(fsrForce, count, corr_Start);

 
  if (Regler_Start == 0)
  {
    int f = 0-10*25;
    Pos_SetValue(353.81,3.8095,22.8571);
   
    Force_SetValue(f);
    Potential();
    Virtual_System(0.099048,0.2,0,-0.04,150);
  }
  else
  {
   
  }
 
   state =!state;     // toggle the state of out put from digital pin 10 high and low
}



For the A, B is the AB signal from hall sensor. use to count the step of the motor.
Quote from: Nick Gammon

[quote author=Nick Gammon link=topic=101224.msg762699#msg762699 date=1334611103


Look, if it takes a week or two to get any code out of you we will get bored. This is the Programming Questions section. You are supposed to post code, and ask questions about it. Not just "I have some code ... why doesn't it work?".


So in the beginnning I only ask if there any code or method ro replace analogRead() and mapping or division which allow the arduino run faster.

AWOL

Quote
So in the beginnning I only ask if there any code or method ro replace analogRead() and mapping or division which allow the arduino run faster.

If you look at the source of "analogRead", you'll see it breaks down into four distinct sections:
1) Select input
2) start conversion
3) wait for end of conversion
4) read and return result of conversion
Of these, 3) takes by far the largest amount of time, around 100 microseconds, and it's a busy-wait, so the processor isn't doing anything else apart from responding to interrupts.
It's fairly simple to separate steps 1) and 2) and then go off and do something useful until you need to read the result.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

dxw00d

Digital pins default to input, so what you are doing is toggling the pullup resistor for pin 10.

Nick Gammon

I have a suggestion.

Set up some debugging pins. Make them outputs (unlike pin 10).

Toggle them at the start of various functions. Then you can see (with a logic analyzer) what is taking the most time.

You can do 10000 analogRead in one second, so that hardly accounts for a throughput of 120.
http://www.gammon.com.au/electronics

hong89


Digital pins default to input, so what you are doing is toggling the pullup resistor for pin 10.


Thanks for the remind =)


Set up some debugging pins. Make them outputs (unlike pin 10).


Sorry that, may I know how to set up the debugging pins?

I have use simple code as below, without the analogRead(0), the output frequency from pin 10 is 57kHz, after add in the analogRead(0), the frequency become 4kHz left. So what is the reason behind that slower the output frequency?

Code: [Select]

int state;

void setup()
{
  Serial.begin(9600);
 
   state = HIGH;
   pinMode(10, OUTPUT);

}

void loop()


digitalWrite (10, state);

//analogRead(0);   
 
   state =!state;
}


Thanks for the help.


Regards

AWOL

#28
Apr 17, 2012, 10:58 am Last Edit: Apr 17, 2012, 11:02 am by AWOL Reason: 1
Quote
So what is the reason behind that slower the output frequency?

I'd expect more like 8kHz, but an analogRead takes (from my memory) around 104us, most of it, as I've already said, is spent in a busy-wait for the end-of-conversion.
digitalWrite is also quite slow, but still doesn't quite account for the 4kHz vs 8kHz expected.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon

#29
Apr 17, 2012, 01:04 pm Last Edit: Apr 17, 2012, 01:25 pm by Nick Gammon Reason: 1
You are mis-interpreting the results.

Making your sketch a bit more efficient, to rule out problems with digitalWrite:

Code: [Select]
byte state;

void setup()
{
 state = HIGH;
 pinMode(10, OUTPUT);
}

void loop()
{  
if (state)
  PORTB |= _BV (2);
else
  PORTB &= ~_BV (2);
analogRead(0);    
state =!state;
}


Results:



Certainly the frequency is 4.46 kHz, but the width of one pulse is 112 uS (see above).

This is because it takes two toggles of pin 10 to provide a single period. So the "frequency" is actually two analog reads, not one.

Now considering the advertised time for analogRead is 100 uS, and the measured time is 112 uS, the extra can be accounted for by the time for the toggling of the pin, the loop, and the if test. Plus analogRead has a certain amount of overhead translating the pin number to a hardware port. But still, it isn't too far off (12 uS) predicted times.

Quote
Hi,  currently my program is too slow(120Hz) ...


4.46 8.92 kHz  (because you double it) is a lot faster than 120 Hz.  In fact 37 74 times as fast. Having said that, floating point maths is slow, this is an 8 bit integer processor.

(edited to allow for the fact that you do two conversions per period).

http://www.gammon.com.au/electronics

Go Up