Servo motor is abnormal because of SD card.

Hi. I'm newbie in Arduino. And i have a trouble. I'm making a security system with 2 sensors, TTL Adafruit Camera, Servo motor, Arduino Uno, and Ethernet shield (for sd card only). If sensor catch a movement, servo motor turns to that sensor, and capture a picture, and save it to SD card. It works till saving to SD card. But while saving picture to SD card, servo motor is atypical. Moving uncontrollable. What should i do? Here is the code:

  #include<Servo.h>
#include<Wire.h>
#include<SPI.h>
#include<SD.h>
#include<SoftwareSerial.h>
#include <Adafruit_VC0706.h>
#define chipSelect 4

#if ARDUINO >=100
SoftwareSerial cameraconnection = SoftwareSerial(2, 3);
#else NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam=Adafruit_VC0706(&cameraconnection);

Servo myservo;
const int sensor1=7;
const int sensor2=8;
const int button= 5;
const int buzz= 6;

int a1, a2, key, val, pos;
void camera1();
void setup(){
  pos=0;
    if(chipSelect !=4) pinMode(4, OUTPUT);                           
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
  } 

  Serial.begin(9600);
  Serial.println("Security Camera");
 
  myservo.attach(9);
  pinMode(buzz, OUTPUT);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(button, INPUT); 
}
void loop(){
  a1= digitalRead(sensor1);
  a2= digitalRead(sensor2);
  key=digitalRead(button);
  if(key==HIGH) {
    if(a1!=HIGH && a2!=HIGH)                        // Both Sensor is deactivated
      val=0;                                        
    if(a1!=HIGH && a2==HIGH)                        // First sensor is deactivated, and second sensor is activated. For this condition, Camera will capture a picture
      val=1;    
    if(a1==HIGH && a2!=HIGH)                        // First sensor is activated, and second is deactivated
      val=2;
    if(a1==HIGH && a2==HIGH)                        // Both sensor is activated
      val=3;
    switch(val){
    case(1):{
      if(pos<45){
        for(; pos <= 45; pos += 1)
      {                                  
        myservo.write(pos);             
        delay(15);                      
      } 
      }
      if(pos>45){
        for(; pos>45; pos-=1){
          myservo.write(pos);
          delay(15);
        }
      }
      digitalWrite(buzz, HIGH);
      camera1();                                    //Jumping to Camera Function
      break;    
    }
    case(2):
      for(; pos <= 135; pos += 1)
      {                                  
        myservo.write(pos);             
        delay(15);                      
      } 
      digitalWrite(buzz, HIGH); 
      break;
    case(3):
      for(; pos <= 135; pos += 1) 
      {                                  
        myservo.write(pos);               
        delay(15);                        
      } 
      for(; pos>=45; pos-=1)     
      {                                
        myservo.write(pos);               
        delay(15);                       
      }
      digitalWrite(buzz, HIGH); 
      break;
    default:
      break;      
    }
  }
  else 
    pos=0;
}
void camera1(){

  // Try to locate the camera
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

  // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 
  // Remember that bigger pictures take longer to transmit!
  
  cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  //cam.setImageSize(VC0706_160x120);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

  Serial.println("Snapping...");
  delay(3000);

  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
  uint16_t  jpglen= cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");
  
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();
  Serial.println("done!");
}

I copied camera codes from Adafruit tutorial. It's capturing picture for only one condition. Sorry for bad language

Uncontrollable servo motion is usually caused by a marginal or improper power supply. Post a diagram showing how everything is wired up. Avoid Fritzing diagrams!

You're not powering the servo from the 5V rail I hope?

SDcards need a lot of power, 100mA to 250mA range, which could be a contributary factor
if you haven't used separate supplies for logic and motor.

The software serial and servo libraries fight. You will need to change one of them. There is a ServoTimer2 library.
When you use several libraries this problem is almost inevitable.

...R

Doh, I should have spotted that... Both use timer1.

So i installed ServoTimer2 library. Compiled code. No difference. Any ideas?. I tried MegaServo library too. And it failed because this library works only with Arduino Mega.

I think you have 6 libraries in your program. There may be other conflicts.

All I can suggests is taking out all but two libraries and trying them.
If they work add one more and see if it still works.
Etc etc until you isolate the problem.

Unfortunately there is no guidance for Arduino library developers so conflicts are common and neither is their good documentation to tell you what resources each libray requires.

...R

TY very much. I'll try that method and update the result :slight_smile:

Robin2:
I think you have 6 libraries in your program. There may be other conflicts.

All I can suggests is taking out all but two libraries and trying them.
If they work add one more and see if it still works.
Etc etc until you isolate the problem.

Unfortunately there is no guidance for Arduino library developers so conflicts are common and neither is their good documentation to tell you what resources each libray requires.

...R

But you should read all the comments in the .h file of the library, that's usually
telling you what you need to know.