Dead Servos

the servos work

the LED's work properly

and we know that avgX and avgY carry the proper values (from 0 to 179).

I can even run a seperate piece of code that is built just to control the servo that shows the connections are right.

Why then do my servos go dead-fish and simply not respond to this code. It looks so right to me!

/*
 ADXL3xx
 
 Reads an Analog Devices ADXL3xx accelerometer and communicates the
 acceleration to the computer.  The pins used are designed to be easily
 compatible with the breakout boards from Sparkfun, available from:
 http://www.sparkfun.com/commerce/categories.php?c=80

 http://www.arduino.cc/en/Tutorial/ADXL3xx

 The circuit:
 analog 0: accelerometer self test
 analog 1: z-axis
 analog 2: y-axis
 analog 3: x-axis
 analog 4: ground
 analog 5: vcc
 
 created 2 Jul 2008
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe 
 
 This example code is in the public domain.

*/


// these constants describe the pins. They won't change:
#include <Servo.h> 

Servo myservo0;
Servo myservo1;  // create servo object to control a servo 
 
int val0;    // variable to read the value from the analog pin 
int val1;

const int groundpin = 18;             // analog input pin 4 -- ground
const int powerpin = 19;              // analog input pin 5 -- voltage
const int xpin = A3;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis of the accelerometer
const int zpin = A1;                  // z-axis


const int arraySize=9;
int Xled1 = 2;
int Xled2 = 3;
int Yled1 = 4;
int Yled2 = 5;

//statement(s);

int sumX=0; 
int avgX=0;
int sumY=0;
int avgY=0;

int xArray[arraySize];
int yArray[arraySize];

void setup()
{
  
  myservo0.attach(8);
  myservo1.attach(9);
  // initialize the serial communications:
  Serial.begin(9600);
  
  // Provide ground and power by using the analog inputs as normal
  // digital pins.  This makes it possible to directly connect the
  // breakout board to the Arduino.  If you use the normal 5V and
  // GND pins on the Arduino, you can remove these lines.
  
  pinMode(groundpin, OUTPUT);
  pinMode(powerpin, OUTPUT);
  pinMode(Xled1, OUTPUT);
  pinMode(Xled2, OUTPUT);
  pinMode(Yled1, OUTPUT);
  pinMode(Yled2, OUTPUT);
  digitalWrite(groundpin, LOW); 
  digitalWrite(powerpin, HIGH);
  
  digitalWrite(7, HIGH);
  
for (int i=0; i<(arraySize+1); i++) {
  xArray[i]=0;
  yArray[i]=0;
}
}
  

void loop()
{
  //Shift whole array
  
for (int i = 0; i < (arraySize - 1); i++) {
xArray[i+1]=xArray[i];
yArray[i+1]=yArray[i];
} 

//take new value
  val0 = analogRead(xpin);
  val0 = map (val0, 267, 400, 0, 179);
  val1 = analogRead(ypin);
  val1 = map (val1, 267, 400, 0, 179);
  


//insert it
xArray[0]=val0;
yArray[0]=val1;
  
  //find average of X
sumX=0;
for (int i = 0; i < arraySize; i++) {
  sumX = sumX + xArray[i];
}
avgX = sumX / (arraySize+1);

   //find average of Y
sumY=0;
for (int i = 0; i < arraySize; i++) {
  sumY = sumY + yArray[i];
}
avgY = sumY / (arraySize+1);

//write to servo  
  myservo0.write(avgX); 
  myservo1.write(avgY); 

  // The following code is just for troubleshooting, it prints a tab between values of in the program
  // the values read properly, as the program is intended:
  Serial.print("avgX=");
  Serial.print(avgX);
  Serial.print("\t");  Serial.print("\t");
  Serial.print("val0=");
  Serial.print(val0);
  Serial.print("\t");  Serial.print("\t");
  Serial.print("avgY=");
  Serial.print(avgY);
  Serial.print("\t");  Serial.print("\t");
  Serial.print("val1=");
  Serial.print(val1);
  Serial.print("\t");  Serial.print("\t");
  // print a tab between values:
  Serial.print("\t");
//  Serial.print(analogRead(zpin));
  Serial.println();
  // delay before next reading:
  delay(50);
  
  
  
  
  
  
    // print the sensor values, and show LEd when past 45 degrees:
  if (analogRead(xpin) < 300)
{
  digitalWrite(Xled1, HIGH);
}
  else
  {
    digitalWrite(Xled1, LOW);
  }
  
  
if (analogRead(xpin) > 366)
{
  digitalWrite(Xled2, HIGH);
}
else
{
  digitalWrite(Xled2, LOW);
}


if (analogRead(ypin) < 308)
{
  digitalWrite(Yled1, HIGH);
}
else
{
  digitalWrite(Yled1, LOW);
}

if (analogRead(ypin) > 376)
{
  digitalWrite(Yled2, HIGH);
}
else
{
  digitalWrite(Yled2, LOW);
}


}

What do your debug prints tell you is happening?

(When posting code, please use the # icon on the editor's toolbar to avoid smilies in your code)

The debug prints give values that are correct and expected that range from 0 to 179 depending on the tilt of the accelerometer (due to gravity of course).
This is for all values of val0, val1, xAvg, and yAvg.

The compile goes smoothly as well saying
"Done uploading"
and...
Binary sketch size: 6514 bytes (of a 258048 byte maximum)

PS: The purpose of this is to make a software based Integral for a PID controller emulator that can keep itself level with these stabilizing systems included. The Integral will just be an average of the last M number of values (as seen in the code), while the Differential will look at the difference of the last N number of values. I only mention this to add as much information as possible. If you can think of an alternative way to avg the last values or an alternative way to feed the servos the data, please, feel free to edit my code, it would be a welcomed help :slight_smile:

I don't understand the "array shift" thing - all you need to do is subtract the oldest reading and add in the newest, you don't need to move anything at all, just increment an array index and bounds-check it.

  for (int i=0; i<(arraySize+1); i++)

In setup - why?
Should be:

  for (int i=0; i < arraySize; i++)

(In fact, the arrays are already reset to zero, so this code is unnecessary)

Pseudo code:

/* Globals */
const int arraySize = 10;
bool avgReady;
int index;
long sum;
int buffer [arraySize];


/* loop code */
int val = analogRead (pin);
sum -= buffer [index];  //subtract oldest value
sum += val;  //add in newest
buffer [index++] = val;
if (index >= arraySize) {
  index = 0;
  avgReady = 1;
}

if (avgReady) {
  avg = (sum + (arraySize / 2)) / arraySize;
}

I think is quicker.

I will certainly implement this method. Thank you!

However I still get the proper values for avgX and avgY, so I would suspect that it is not related to the servo problem. But I am very grateful for this coding insight, I will be looking more into it.

Here is an interesting fact... I can replace avgX and avgY with numbers

for example:

myservo0.write(50);

and the servo STILL does not respond....

HOWEVER on the same token

I can run the example servo "knob" code doing the exact same thing
(using numbers), and the servo responds.

However I still get the proper values for avgX and avgY, so I would suspect that it is not related to the servo problem

But having exceeded the bounds of your arrays in setup, all bets about variables beyond the arrays are off.

AWOL:

However I still get the proper values for avgX and avgY, so I would suspect that it is not related to the servo problem

But having exceeded the bounds of your arrays in setup, all bets about variables beyond the arrays are off.

Okay, is it possible this array error could also explain why when I changed it to
myservo0.write(50);
With no variables at all, why my servo remained still?

Yes. 'myservo0' is a variable... and it has member variables. By selecting an array index that you have not allocated to the array, you write to a piece of memory that may have been allocated to the Servo object - thus causing a failure. If the 'Knob' sketch works, it's not a hardware issue.