Pages: 1 [2] 3 4   Go Down
Author Topic: Speed up arduino  (Read 5216 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25768
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
fsrConductance = 1000000;           // we measure in micromhos so
    fsrConductance = fsrResistance;
I suppose you can hope the compiler optimises-out pointless assignments.
Logged

"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.

Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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;
    } 
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
 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:
        enable=4.5;
enable is an int!
« Last Edit: April 16, 2012, 05:23:55 am by PaulS » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25768
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

"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.

Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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?
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25768
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

"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.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?".
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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:
  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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25768
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

"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.

Gosport, UK
Offline Offline
Faraday Member
**
Karma: 21
Posts: 3113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25768
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: April 17, 2012, 04:02:38 am by AWOL » Logged

"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.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are mis-interpreting the results.

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

Code:
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).

« Last Edit: April 17, 2012, 06:25:34 am by Nick Gammon » Logged

Pages: 1 [2] 3 4   Go Up
Jump to: