Motor spinning when serial writes

Hi,

I have an Arduino Uno with a Sparkfun ESP8266 Wifi Shield. I’ve just added a continuous servo to the mix, but it seems that the motor is interfering with the Serial.write commands. I have the serial monitor open, and the motor speeds up whenever something is being printed.

I was hoping someone could point me in the right direction, whether this is likely a hardware issue or a problem with my understanding.

It’s hard to imagine crossed wires, since it’s just this shield, with the motor in 5V, GND, and Pin 4.

My code is quite long, most of it is the working wifi module code.

//////////////////////
// Library Includes //
//////////////////////
// SoftwareSerial is required (even you don't intend on
// using it).
#include <SoftwareSerial.h>
#include <SparkFunESP8266WiFi.h>
#include <Servo.h>

Servo servo1; 


//light stuff
//int redPin = 13;
//int greenPin = 12;
//int bluePin = 11;
//#define COMMON_ANODE
boolean marker = false;
char inData[25]; // Allocate some space for the string
String results;
char inChar; // Where to store the character read
byte index = 0; // Index into array; where to store the character

//////////////////////////////
// WiFi Network Definitions //
//////////////////////////////
// Replace these two character strings with the name and
// password of your WiFi network.
const char mySSID[] = "My SSID";
const char myPSK[] = "mypassword";

//////////////////////////////
// ESP8266Server definition //
//////////////////////////////
// server object used towards the end of the demo.
// (This is only global because it's called in both setup()
// and loop()).
ESP8266Server server = ESP8266Server(80);

//////////////////
// HTTP Strings //
//////////////////
const char destServer[] = "www.mysever.com";
const String htmlHeader = "HTTP/1.1 200 OK\r\n"
                          "Content-Type: text/html\r\n"
                          "Connection: close\r\n\r\n"
                          "<!DOCTYPE HTML>\r\n"
                          "<html>\r\n";

const String httpRequest = "GET /key/status.txt HTTP/1.1\nHost: www.myserver.com\nConnection: close\n\n";

// All functions called from setup() are defined below the
// loop() function. They modularized to make it easier to
// copy/paste into sketches of your own.
void setup()
{
  
  servo1.attach(4);

  // Serial Monitor is used to control the demo and view
  // debug information.
  Serial.begin(9600);
  serialTrigger(F("Press any key to begin."));

  // initializeESP8266() verifies communication with the WiFi
  // shield, and sets it up.
  initializeESP8266();

  // connectESP8266() connects to the defined WiFi network.
  connectESP8266();


  // displayConnectInfo prints the Shield's local IP
  // and the network it's connected to.
  displayConnectInfo();

  serialTrigger(F("Press any key to connect client."));
  clientDemo();

  serialTrigger(F("Press any key to test server."));
  serverSetup();
}

void loop()
{
  serverDemo();
}

void initializeESP8266()
{
  // esp8266.begin() verifies that the ESP8266 is operational
  // and sets it up for the rest of the sketch.
  // It returns either true or false -- indicating whether
  // communication was successul or not.
  // true
  int test = esp8266.begin();
  if (test != true)
  {
    Serial.println(F("Error talking to ESP8266."));
    errorLoop(test);
  }
  Serial.println(F("ESP8266 Shield Present"));
  //setColor(0,0,255);
}

void connectESP8266()
{
  // The ESP8266 can be set to one of three modes:
  //  1 - ESP8266_MODE_STA - Station only
  //  2 - ESP8266_MODE_AP - Access point only
  //  3 - ESP8266_MODE_STAAP - Station/AP combo
  // Use esp8266.getMode() to check which mode it's in:
  int retVal = esp8266.getMode();
  if (retVal != ESP8266_MODE_STA)
  { // If it's not in station mode.
    // Use esp8266.setMode([mode]) to set it to a specified
    // mode.
    retVal = esp8266.setMode(ESP8266_MODE_STA);
    if (retVal < 0)
    {
      Serial.println(F("Error setting mode."));
      errorLoop(retVal);
    }
  }
  Serial.println(F("Mode set to station"));

  // esp8266.status() indicates the ESP8266's WiFi connect
  // status.
  // A return value of 1 indicates the device is already
  // connected. 0 indicates disconnected. (Negative values
  // equate to communication errors.)
  retVal = esp8266.status();
  if (retVal <= 0)
  {
    Serial.print(F("Connecting to "));
    Serial.println(mySSID);
    // esp8266.connect([ssid], [psk]) connects the ESP8266
    // to a network.
    // On success the connect function returns a value >0
    // On fail, the function will either return:
    //  -1: TIMEOUT - The library has a set 30s timeout
    //  -3: FAIL - Couldn't connect to network.
    retVal = esp8266.connect(mySSID, myPSK);
    if (retVal < 0)
    {
      Serial.println(F("Error connecting"));
      errorLoop(retVal);
    }
  }
}

void displayConnectInfo()
{
  char connectedSSID[24];
  memset(connectedSSID, 0, 24);
  // esp8266.getAP() can be used to check which AP the
  // ESP8266 is connected to. It returns an error code.
  // The connected AP is returned by reference as a parameter.
  int retVal = esp8266.getAP(connectedSSID);
  if (retVal > 0)
  {
    Serial.print(F("Connected to: "));
    Serial.println(connectedSSID);
  }

  // esp8266.localIP returns an IPAddress variable with the
  // ESP8266's current local IP address.
  IPAddress myIP = esp8266.localIP();
  Serial.print(F("My IP: ")); Serial.println(myIP);
}

void clientDemo()
{
  // To use the ESP8266 as a TCP client, use the
  // ESP8266Client class. First, create an object:
  ESP8266Client client;

  // ESP8266Client connect([server], [port]) is used to
  // connect to a server (const char * or IPAddress) on
  // a specified port.
  // Returns: 1 on success, 2 on already connected,
  // negative on fail (-1=TIMEOUT, -3=FAIL).
  int retVal = client.connect(destServer, 80);
  if (retVal <= 0)
  {
    Serial.println(F("Failed to connect to server."));
    return;
  }

  // print and write can be used to send data to a connected
  // client connection.
  client.print(httpRequest);


  

    while(client.available() > 0)
    {

        results = client.readStringUntil('?');
        
    }

  //Serial.println(results);

  //hold or drop
  if(results.indexOf('drop') > 0){
    Serial.println("Drop the key");
    servo1.write(100);
    delay(20000);
  } else {
    Serial.println("Pending");
  }
  
  if (client.connected())
    client.stop(); // stop() closes a TCP connection.

  delay(4000);
  clientDemo();
}

void serverSetup()
{
  // begin initializes a ESP8266Server object. It will
  // start a server on the port specified in the object's
  // constructor (in global area)
  server.begin();
  Serial.print(F("Server started! Go to "));
  Serial.println(esp8266.localIP());
  Serial.println();
  //setColor(40, 255, 0);
}

void serverDemo()
{
  // available() is an ESP8266Server function which will
  // return an ESP8266Client object for printing and reading.
  // available() has one parameter -- a timeout value. This
  // is the number of milliseconds the function waits,
  // checking for a connection.
  ESP8266Client client = server.available(500);

  if (client)
  {
    Serial.println(F("Client Connected!"));
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected())
    {
      if (client.available())
      {
       //code removed for forum characer limit
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);

    // close the connection:
    client.stop();
    Serial.println(F("Client disconnected"));
  }

}

// errorLoop prints an error code, then loops forever.
void errorLoop(int error)
{
  Serial.print(F("Error: ")); Serial.println(error);
  Serial.println(F("Looping forever."));
  for (;;)
    ;
}

// serialTrigger prints a message, then waits for something
// to come in from the serial port.
void serialTrigger(String message)
{
  Serial.println();
  Serial.println(message);
  Serial.println();
  while (!Serial.available())
    ;
  while (Serial.available())
    Serial.read();
}

void setColor(int red, int green, int blue)
{
#ifdef COMMON_ANODE
  //red = 255 - red;
  //green = 255 - green;
  //blue = 255 - blue;
#endif
  //analogWrite(redPin, red);
  //analogWrite(greenPin, green);
  //analogWrite(bluePin, blue);
}

I don't know about the problem that you reported, but

  if (results.indexOf('drop') > 0)

is not going to do what you think because the parameter you are using is not a string

That part works. Isn't it a string because of:

results = client.readStringUntil('?');

'drop' is neither a String or a char, which is what readStringUntil() takes as a parameter

A String needs double quotes round it and a char can only be a single character

You seem to be drawing power for the servo from the Arduino - that can cause the Arduino to malufunction and may even damage it. Give the servo its own power supply with a common GND with the Arduino.

...R

Thanks for your help, I've given the motor it's own 9V battery. It still seems to spin whenever there is a Serial.print. Should I just be removing all of my serial printing?

Robin2:
Give the servo its own power supply with a common GND with the Arduino.

Or, just use the Vin pin and rely on power regulated by your USB source.

UKHeliBob:
‘drop’ is neither a String or a char, which is what readStringUntil() takes as a parameter
A String needs double quotes round it and a char can only be a single character

Interestingly, character literals longer than one char are evaluated as int data type in C++. that’s why you don’t see an error when you compile. you can see this for yourself:

Serial.println('AB', HEX); // << add characters one at a time and take not of what happens

evaluates as the ASCII value and will print:

4142

therefore, ‘drop’ evaluates to:

6F70

indexOf() is a String function that expects a String or const char*, you are handing it an int. In order to do what you want, you need to put that string in double quotes…

if (results.indexOf("drop") > 0)

It can be a challenge jumping back and forth between C++ and JavaScript!

I've given the motor it's own 9V battery

If the battery is the type with 2 terminals on the top, that I know as a PP3, then it is not going to last long. There is also the question as to whether the "servo" is rated for 9V

As to the original problem, it sounds like the system may be using the Serial pins (0 and 1) for other purposes which is causing the interaction, but I don't see how.

micomator: Thanks for your help, I've given the motor it's own 9V battery. It still seems to spin whenever there is a Serial.print. Should I just be removing all of my serial printing?

common ground?

Are the two GND pins on my arduino common ground with each other? And would you second the Vin Pin idea over a second power source?

I figured the arduino would be communicating to the board through a couple pins, but I'm not sure how this could find it's way to the other pins, unless you think grounding could be related.

I've tried wiring it so everything goes through the same ground pin on the arduino, still has the same effect of responding to serial.write. I've also tried just using the VIN, same again.

Can I use the digital IO pins to control this motor? I notice the wifi shield has some extra pins/holes up the top side.

You should check this too... it looks like the switch on the shield is set to SW, perhaps try HW (hardware serial)

your servo should work if attached power to Vin, ground to any ground and the input to Pin 4 (as you have it).

So versus your photo, look at moving the power line on the servo to Vin as the only change (besides the HW switch).

As I understand it, flicking that switch will cause my code to upload to the wifi shield instead of the arduino.

It does work though, if I change it to HW, I just lose any feedback from the serial port. Looks like the way to go is to remove any serial writing or commands, and maybe use a colored LED for feedback? What do you think?

micomator: As I understand it, flicking that switch will cause my code to upload to the wifi shield instead of the arduino.

It does work though, if I change it to HW, I just lose any feedback from the serial port. Looks like the way to go is to remove any serial writing or commands, and maybe use a colored LED for feedback? What do you think?

You mean the USB hardware Serial port? well, the next option is software serial 9&10 but you have to then hook that up to something to see the data.

Since you are attached to WiFi, perhaps you could try logging over UDP. I'm not at all familiar with that particular library but you should be able to do that.