Pages: [1]   Go Down
Author Topic: Stepper library question (passing variables)  (Read 592 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Having a strange problem...

I am developing a function that takes in some parameters and uses those to scan a stepper motor over some angle. Attached to the motor is a solar panel, with its output attached to an ADC. Basically it scans a range, picks a point with the highest value, and moves the cell to that orientation. A somewhat crude prototype of sun-tracking.

Anyhow, I'm using the Stepper library included with the IDE, and this code works fine if I input a number like so: myStepper.step(-50). However, if I pass it an integer with that same value, nothing happens. I get no errors during compile, but the motor just doesn't turn. This is the ONLY change I am making as I try each way.

Code:
/*This will sweep a stepper motor through the designated angle while reading ADC values.
  
  During the sweep the voltage of the solar cell will be read and stored in an array. At the conclusion of the
  sweep, the maximum value will be found and the number of steps needed to return to the corresponding position
  will be returned.

  Name: Sergey Feingold
  Date: 9-16-11
  
  --Inputs--
  angle: This is the angle in degrees through which the stepper will move. The starting position is assumed to
  bisect the angle, therefore an input of 180 will sweep 90° each direction before returning to center.
  stepsPerRev: The is the number of steps per revolution of the stepper motor. This is required to ensure correct
  amount of movement.
  numAverages: This is the number of times that the ADC value will be averaged at each step. More averages will result in a slower sweep.
  pinADC: This is the ADC pin that will be be analyzed
*/



void sweep(int angle, int stepsPerRev, int numAverages, int pinADC)
  {
    // Stepper Parameters
    myStepper.setSpeed(25);
    const int stepsPerRevolution = stepsPerRev;
    char cellVoltages[200];
    int currentStep = 0;
    int stepCount = 0;
    int totalSteps = (angle/360)*400;
    int halfSweep = totalSteps/2;
    int CW = 1;
    int CCW = -1;
    int halfSweepCW = halfSweep * CW;
    int halfSweepCCW = halfSweep * CCW;
    myStepper.step(halfSweepCW);  
    
    
  }




Any thoughts? I glanced at Stepper.cpp to examine that function but I can't see any obvious reason why an integer shouldn't work.

As a tangential issue, is there a "cheap" way to do quadratic interpolation? I will start by using a simple function to find the maximum value of the ADC, but of course it is likely there will be multiple and equal maximums. How to circumvent this?

Any help is appreciated! These forums are wonderful.
« Last Edit: September 16, 2011, 03:42:11 pm by SVFeingold » Logged

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12194
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Change this line:
Code:
   int totalSteps = (angle/360)*400;
to this:
Code:
   int totalSteps =(int) (((long)angle) * 400 / 360) ;

Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Perfect!

I only realized after I posted this that I may not even be getting the right value to that integer; I tried setting it manually right before the step function and then it worked so I got as far as seeing a serial printout of all the variables, all equal to zero, right before I saw your post.

I'm satisfied but would like to know what exactly is going on here. I assumed that since both variables were declared as integers, that they would remain that way, i.e. any possible remainders were discarded; integers should also be enough to hold any values here. Apparently that is not the case, but I don't know why. I'm also not grasping the significance of swapping the operators.

Thanks for your help!
Logged

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12194
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In integer division 359/360 = 0
So  a/360*400 won't change from 0 till a is 360.  a*400/360 on the other hand is more useful (but might overflow a 16 bit int).
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ahh I see. Funny how you never remember these things when you need them. At least I don't. Thanks!
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Having another issue and I don't think I should open another thread for it...

I'm calling a function that averages some number of samples. It returns a variable "average." Some math is done on this to get it into the right format, and it's then either displayed on a screen or viewed through the serial monitor.

Problem is that when the ADC result goes above a certain value, the number becomes negative. Normally I'd suspect a rollover issue but I don't see why this should happen with a long integer...the (final) number never goes above about 600. Below that, say around 450 and under, it works as it should.

For example, here's a call to the function that exhibits that behavior:

Code:
   
long int cellVoltage = 0;
long int cellVoltages[totalSteps];
long int runAverage = 0;
for (int i = 0; i < totalSteps; i++)
    {
        runAverage = runningAVG(pinADC,numAverages);
        cellVoltages[i] = (runAverage * 1100) / 1024; // Convert reading to Voltage
        //cellVoltage = averageVoltage;
       
        //cellVoltages[i] = cellVoltage;
        myStepper.step(-1);
    }

The ADC code works fine, it's used elsewhere with correct results. So, the maximum output from the ADC would be 1023. 1023 * 1100 = 1,125,300. So far that should be well within the range of a long int. Then 1,125,300 / 1024 = 1098.93. Since it is a long int, I would assume that the decimal part would be discarded, leaving you with an integer with value 1098. This is the only area I can think of where I could be missing something. So what's going on?
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've also noticed that I can get a value of 465, and upon increasing the light slightly (the light shining on the solar cell, which is connected to the ADC) the value changes to -460. Seems backwards to me.

What's more confusing, I use the same code elsewhere and it works fine:

Code:
long int runAverage = 0;
long int cellVoltage = 0;

runAverage = runningAVG(cellPin,5);
cellVoltage = (runAverage*1100) / 1024; // Convert reading to Voltage

« Last Edit: September 16, 2011, 03:41:43 pm by SVFeingold » Logged

Offline Offline
God Member
*****
Karma: 4
Posts: 813
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The ADC code works fine, it's used elsewhere with correct results. So, the maximum output from the ADC would be 1023. 1023 * 1100 = 1,125,300. So far that should be well within the range of a long int.

If the value 1023 and 1100 are both stored in "int" variables instead of "long int" variables, then the calculation will truncate to "int" (which is 16 bits on AVR) before being converted to "long int." You may want to explicitly cast each value to (long int) when you do math on it.

Also, you're not posting code for the runningAVG function -- are you sure that works as expected?
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If the value 1023 and 1100 are both stored in "int" variables instead of "long int" variables, then the calculation will truncate to "int" (which is 16 bits on AVR) before being converted to "long int." You may want to explicitly cast each value to (long int) when you do math on it.

Also, you're not posting code for the runningAVG function -- are you sure that works as expected?

I was sure until I looked at it. I found the problem thanks to your advice but I'll post the code anyway:

Code:
int runningAVG(const int sensorPin, const int numReadings)
{

// ADC Smoothing parameters
long int readings[numReadings];      // the readings from the analog input
long int total = 0;                  // the running total
long int average = 0;                // the average

for (int thisReading = 0; thisReading < numReadings; thisReading++) readings[thisReading] = 0; // Resets all contents of "readings" to zero
   
 /* This code performs a running average on the selected pin with number of samples defined by "numReadings"*/
  for (int index = 0; index < numReadings; index++)
  {
    total = total - readings[index];   // subtract the last reading:     
    readings[index] = analogRead(sensorPin);    // read from the sensor:
    total = total + readings[index];     // add the reading to the total:   
    if (index >= numReadings) index = 0;        // if we're at the end of the array wrap around to the beginning:       
  }
  average = total / numReadings;     // calculate the average:
  return average;

}

I already changed the code by adding "long int" in front of the declarations for "readings[numReadings]" and "total." Even though average was a long int I guess that property wasn't passed on through the return. Everything seems to work now. Thanks!
Logged

Pages: [1]   Go Up
Jump to: