Servo Command

Hello,

I am programming a code to make my servo motor turn to 3 different angles when receiving corresponding commands over bluetooth. I am using the NRF8001 and bluefruit app on Iphone 5.

So far I am able to send a code over bluetooth from my phone and the servo motor will move to the corresponding location. My first command ‘1’ turns the motor to the location instantly. Second command ‘2’ turns the motor to the destination after 1 second. Third command ‘3’ turns the motor to the destination after 2 seconds. Why is there a time delay in the second and third command. Any suggestions on how to fix this. I am using the echodemo from adafruit to establish communication.

Codes below.

COMMAND CODE

if (status == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial.available() > 0) {
     incomingByte = BTLEserial.read();

     if (incomingByte == '1') 
       myservo.attach(8);
       myservo.write(180);
       delay(900);
       myservo.detach();
     if (incomingByte == '2')
       myservo.attach(8);
       myservo.write(-180);
       delay(900);
       myservo.detach();
     if (incomingByte == '3')
       myservo.attach(8);
       myservo.write(-180);
       delay(450);
       myservo.detach();

FULL CODE

#include <SPI.h>
#include "Adafruit_BLE_UART.h"
#include <Servo.h>
Servo myservo;
int incomingByte;
int pos = 0;


#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2     
#define ADAFRUITBLE_RST 9

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);


void setup(void)//********************
{ 
  Serial.begin(9600);
  while(!Serial); // Leonardo/Micro should wait for serial init
  Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Print echo demo"));

  // BTLEserial.setDeviceName("NEWNAME"); /* 7 characters max! */

  BTLEserial.begin();
  myservo.attach(8);
}


aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

void loop()//**********************
{
  // Tell the nRF8001 to do whatever it should be working on.
  BTLEserial.pollACI();

  // Ask what is our current status
  aci_evt_opcode_t status = BTLEserial.getState();
  // If the status changed....
  if (status != laststatus) {
    // print it out!
    if (status == ACI_EVT_DEVICE_STARTED) {
        Serial.println(F("* Advertising started"));
    }
    if (status == ACI_EVT_CONNECTED) {
        Serial.println(F("* Connected!"));
    }
    if (status == ACI_EVT_DISCONNECTED) {
        Serial.println(F("* Disconnected or advertising timed out"));
    }
    // OK set the last status change to this one
    laststatus = status;
  }

  if (status == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial.available() > 0) {
     incomingByte = BTLEserial.read();

     if (incomingByte == '1') 
       myservo.attach(8);
       myservo.write(180);
       delay(900);
       myservo.detach();
     if (incomingByte == '2')
       myservo.attach(8);
       myservo.write(-180);
       delay(900);
       myservo.detach();
     if (incomingByte == '3')
       myservo.attach(8);
       myservo.write(-180);
       delay(450);
       myservo.detach();
   
     

       
    }
    

       
    // OK while we still have something to read, get a character and print it out
    while (BTLEserial.available()) {
      char c = BTLEserial.read();
      Serial.print(c);
    }
      

    // Next up, see if we have any data to get from the Serial console

    if (Serial.available()) {
      // Read a line from Serial
      Serial.setTimeout(100); // 100 millisecond timeout
      String s = Serial.readString();

      // We need to convert the line to bytes, no more than 20 at this time
      uint8_t sendbuffer[20];
      s.getBytes(sendbuffer, 20);
      char sendbuffersize = min(20, s.length());

      Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");

      // write the data
      BTLEserial.write(sendbuffer, sendbuffersize);
    }
  }
}

If you want a program to be responsive don't use the delay() function anywhere. Use millis() to manage timing as illustrated in Several Things at a Time

You have several lines of code in loop() that only need to be done once in setup() - such as attaching the servo and setting the Serial timeout()

You probably should not use Serial.readString() at all as it can delay until it times out. Use one of the examples in Serial Input Basics - probably the 2nd one. They are simple, reliable and non-blocking.

...R

I read your code on the millis function. I realize that it will work for my problem. I am unable to understand your servo millis code though as it has a lot of different features. Is there another code using a servo and millis that is less complicated than I can look at.

This is the servo function from Several Things at a Time

void servoSweep() {

     // this is similar to the servo sweep example except that it uses millis() rather than delay()

     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative

   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees;
   }
       // make the servo move to the next position
   myservo.write(servoPosition);
       // and record the time when the move happened
 }
}

If you explain what you don’t understand I will try to help.

…R

if (incomingByte == '1') 
       myservo.attach(8);
       myservo.write(180);
       delay(900);
       myservo.detach();
     if (incomingByte == '2')
       myservo.attach(8);

Because you're not using braces after your conditions, your delays are cumulative.

Why do you keep attaching and detaching the servo?