Use The Data In SD card To Run The Servo Motor

Hi Friends! I could read the data stored in the SD card through Serial monitor as 0 0 0 4 8 20 16 50 etc.. But I couldn't use the data to turn the Servo Motor.

This is what I have done. I tried to move the data in the SD card to a variable named “data”. But once the programmed is uploaded I get no values printed in the Serial Monitor

This is the code I have uploaded to the arduino

#include <Servo.h>

Servo myservo;

int pos = 0;

#include <SD.h>
int CS_pin = 53;
float refresh_rate = 0.0;
int data;
void setup()
{
myservo.attach(3); // attaches the servo on pin 3 to the servo object

Serial.begin(9600);

Serial.print(“Initializing SD card…”);

pinMode(CS_pin, OUTPUT);

if(!SD.begin(CS_pin))
{
Serial.println(“FAILED”);
return;
}
Serial.println(“READY”);
}

void loop()
{
File myFile = SD.open(“test.txt”);

if (myFile) {
Serial.println(“test.txt:”);

while (myFile.available())
{
delay(200);
data=myFile.read();
Serial.write(myFile.read());

if (data == 20)
{
myservo.write(pos); //if the data in SD is 20,turn the Servo in clockwise
pos=pos++;
delay(10);
}
if (data == 50)
{
myservo.write(pos); //if the data in SD is 50,turn the Servo in counter-clockwise
pos=pos–;
delay(10);
}

}

myFile.close();
}
else {

Serial.println(“error opening test.txt”);
}
delay(5000);
}

You're reading and throwing away every other character when you print it. Try changing this:

        data=myFile.read();
       Serial.write(myFile.read());

to this:

        data=myFile.read();
       Serial.write(data);

I get the values displayed on Serial Monitor. But it has no effect on the Servo Motor attached on pin 3.

Post. Your. Code.

Use code tags this time, please.

Is the data in the file ASCII or raw bytes?

This is my modified code

#include <Servo.h> 
 
Servo myservo;  
 
int pos = 0;    // variable to store the servo position 

#include <SD.h>
int CS_pin = 53;
float refresh_rate = 0.0;
int data;

void setup()
{
   myservo.attach(3);  // attaches the servo on pin 3 to the servo object 
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  pinMode(CS_pin, OUTPUT);
  
if(!SD.begin(CS_pin))
  {
    Serial.println("FAILED");
    return;
  }
  Serial.println("READY");
}

void loop()
{
  File myFile = SD.open("test.txt");
  
if (myFile)
{
    Serial.println("test.txt:");
    
    while (myFile.available()) 
    {
        delay(200);
        data=myFile.read();
    	Serial.write(data);
    if (data == 20)        
 {
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    pos=pos++;
    delay(10);
  } 
if (data == 50)      
  {
    myservo.write(pos);
    pos=pos--;
    delay(10);
}

    }
myFile.close();
  } 
else 
{
  	Serial.println("error opening test.txt");           // if the file didn't open, print an error:
  }
  
delay(5000);
}

Try this...

        data=myFile.read();
      Serial.println(data,DEC);

This will show you the values of the bytes stored in your data file. You will probably find that it doesn't look like what you are expecting.

The values stored in the file are probably ascii. A line like

20

is stored as the character '2' followed by the character '0' followed by the linefeed character and the carriage return character.

You were right I get unexpected values. I entered the value 0 (only zeros) in the SD card and read it. Now I get a combination of 3 values for a single ASCII character 0. And now the data read through Serial Monitor is 48 13 10 48 13 10 48 13 10 etc.. And similarly for the value 20 in SD card it's been displaying 50 48 13 10 50 48 13 10 etc..

#include <Servo.h> 
 
Servo myservo;  
 
int pos = 0;    // variable to store the servo position 

#include <SD.h>
int CS_pin = 53;
float refresh_rate = 0.0;
int data;
void setup()
{
   myservo.attach(3);  // attaches the servo on pin 3 to the servo object 
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  pinMode(CS_pin, OUTPUT);
 
 if(!SD.begin(CS_pin))
  {
    Serial.println("FAILED");
    return;
  }
  Serial.println("READY");
}

void loop()
{
  File myFile1 = SD.open("tests.txt");
  if (myFile1) 
{
    Serial.println("tests.txt:");
    
    while (myFile1.available()) 
    {
        delay(500);
        data=myFile1.read();
    	Serial.println(data,DEC);
   
 if (data == 48)                       //triangle 
 {
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    pos=pos++;
    delay(10);
  } 

if (data == 13)                        //square
  {
    myservo.write(pos);              // tell servo to go to position in variabon 
    pos=pos--;
    delay(10);
}

    }
    myFile1.close();
  } 
else 
{
    Serial.println("error opening tests.txt");
  }
  delay(5000);
}

I tried to control the servo motor with the values obtained from the above program from the SD. But it doesn't work. There is no response from the servo attached to pin 3.

How is the servo powered?

Can you make it move with a simpler program - e.g. the sweep example?

Prasanth94: You were right I get unexpected values. I entered the value 0 (only zeros) in the SD card and read it. Now I get a combination of 3 values for a single ASCII character 0. And now the data read through Serial Monitor is 48 13 10 48 13 10 48 13 10 etc.. And similarly for the value 20 in SD card it's been displaying 50 48 13 10 50 48 13 10 etc..

Look at those values then find an ASCII table on the Web. Now do they make sense ? What characters are associated with ASCII decimal 48 and 50, for instance ?

Servo works pretty well in the two sample programs - Sweep and Knob

48 and 50 are the ASCII values of 0 and 2. 13 and 10 are the ASCII values of Line feed and Carriage return. I tried to use these values but there is no response from the servo motor.

This is weird:

    pos=pos++;

try

    pos++;

instead.

Also, ignore character 13 for now. Once you've got your increment & decrement sorted out, 48 increments and the 13 that immediately follows undoes it - resulting in no movement.

Prasanth94: 48 and 50 are the ASCII values of 0 and 2. 13 and 10 are the ASCII values of Line feed and Carriage return. I tried to use these values but there is no response from the servo motor.

So, you enter 20 and get 50 and 48 (2 and 0 in ASCII). So far so good, but the servo library does not understand ASCII characters so you need to convert them to something that it does understand. One way to do that is to put the bytes as they arrive into an array of chars with a zero in the last position in the array. Now you have a C style string (note, not a String). You can now convert the array into an integer to be used by the servo using the atoi() function which, roughly speaking, converts ASCII to integer, hence its name.

Take a look at Serial input basics to see how to do it.