Servo motor cuts out the rest of the loop

#include <SoftwareSerial.h>
#include <Adafruit_GPS.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <Servo.h>
Servo servo;

#define BME_SCK 10
#define BME_MISO 16
#define BME_MOSI 14
#define BME_CS 15

#define SEALEVELPRESSURE_HPA (1028.68) // Meet de druk op de grond!

Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);
SoftwareSerial mySerial(8, 7); // (TX, RX)
Adafruit_GPS GPS(&mySerial);

void setup() {

  Serial.begin(9600);
  mySerial.begin(9600);

// BME680

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }
  
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms
  delay(5000);

// GPS

  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  GPS.sendCommand(PGCMD_ANTENNA);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);

  servo.attach(6);
}

uint32_t timer = millis();

void loop() {
  
// Parsing

char c = GPS.read();
  if ((c))
  if (GPS.newNMEAreceived()) {
  if (!GPS.parse(GPS.lastNMEA()))
      return;
  }

  if (millis() - timer > 2000) {
    timer = millis();
    
// GPS

    if (GPS.fix) {          
      Serial.print("\n");
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.println(GPS.longitude, 4); Serial.println(GPS.lon);
      mySerial.print("\n");
      mySerial.print("Location: ");
      mySerial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      mySerial.print(", ");
      mySerial.println(GPS.longitude, 4); Serial.println(GPS.lon);
    }
    
// BME680

      Serial.print("Temperature = ");
      Serial.print(bme.temperature);
      Serial.println(" *C");
      mySerial.print("Temperature = ");
      mySerial.print(bme.temperature);
      mySerial.println(" *C");
    
      Serial.print("Pressure = ");
      Serial.print(bme.pressure / 100.0);
      Serial.println(" hPa");
      mySerial.print("Pressure = ");
      mySerial.print(bme.pressure / 100.0);
      mySerial.println(" hPa");
      
      Serial.print("Humidity = ");
      Serial.print(bme.humidity);
      Serial.println(" %");
      mySerial.print("Humidity = ");
      mySerial.print(bme.humidity);
      mySerial.println(" %");
      
      Serial.print("Gas = ");
      Serial.print(bme.gas_resistance / 1000.0);
      Serial.println(" KOhms");
      mySerial.print("Gas = ");
      mySerial.print(bme.gas_resistance / 1000.0);
      mySerial.println(" KOhms");
    
      Serial.print("Approx. Altitude = ");
      Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
      Serial.println(" m");
      mySerial.print("Approx. Altitude = ");
      mySerial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
      mySerial.println(" m");

      servo.write(30);
      delay(500);
      servo.write(0);
       delay(500);
  }
}

So for the last few months I’ve been working on a project. I’m designing a “satellite” that will be dropped from the air at a height of 1 km. The idea is that I will measure air temperature, - pressure and humidity and also give the exact location using a GPS. All the software for these things are done and they all work. The only problem is the landing. When the CanSat (that’s what our “satellite” is called) hits the 100 m mark, after a drop of 900 m, the parachute should deploy. We dicided to do this by wrapping an elastic band around the parachute and placing the elastic around the arm of a servo motor. However, the servo motor won’t work. Every time I attach the servo with the command servo.attach(6); the loop stops. If this command is commented I keep getting the stats as I wish but as soon as I uncomment it, I only get the stats 1 time before the loop cuts out. Does anyone know what the problem is? I’m dying for help. :frowning:

Servo.h and SoftwareSerial.h do not work well together. Try using ServoTimer2 instead of Servo. You'll need to change the write() values because it uses microseconds not angles. Otherwise there are several alternatives to SoftwareSerial but I've not used them myself.

If that doesn't help there may also be conflicts with some of the other libraries.

Steve

Oh that's very helpful thank you! Could you list the commands? I assume i'll need a new library too.

NeoSWSerial and AltSoftSerial are better software serial libraries, but you still have to check for timer conflicts with other libraries, like Servo.

The servo must be powered separately from the Arduino (and certainly not from the 5V output). Don’t forget to connect all the grounds!

Oh so 3.3 volt for the servo? May I ask why it needs to be powered seperately? Also, what is "seperately" another battery or another cirquit on the same bettery?

Most servos require 4.8 to 6 (sometimes 7.4) V. A 4xAA battery pack will work for one or two small servos.

Servos and motors inject severe electrical noise into the power supply, which can damage the Arduino and/or cause it to malfunction, and the Arduino on board regulator cannot safely supply enough current to run a motor or servo.

You will see lots of bad tutorials that say otherwise, but if you want your project to work when it needs to work, ignore such bad advice.

ServoTimer.h is the new library you'll need. The commands are the same except, as I said earlier, write() takes ms not angles. So write(0) becomes write(1000) and write(180) would be write(2000).

For power, 4 x 1.2V NiMH rechargeable AA batteries (Eneloops etc) are ideal as they can handle high currents better than standard AAs.

Steve

I use a TIANKONGRC SG90 and I googled the name, it indeed says 4.8 - 6 V. Does that mean I can use 5V? We aren't able to just add another battery pack as it wouldn't fit in the CanSat. I can just put the Digital Connection on pin 6 and put the GND and VCC directly on the battery that's also in another cirquit with the whole arduino tho right?

slipstick:
ServoTimer.h is the new library you'll need.

When I google it I see "Servotimer2.h" alot. Is this correct? Could you otherwise send a link please

Typo. Yes it’s GitHub - nabontra/ServoTimer2: ServoTimer2 is a simple library for Arduino 1.x that does not use Timer1 in case of a conflict. I had it right the first time I gave you the name.

The rest is impossible to answer without knowing what “the Digital connection” and the existing battery are. Why not draw a simple schematic of what you are proposing. It would also help to know what Arduino you’re using.

Steve

I'm using a Pro Micro and attached are:

BME680: pin 15, 14, 16, 10 + GND & VCC
Ultimate GPS Breakout v3: pin 7, 8 + GND & VCC
APC220: pin 7, 8 + GND & VCC
microSD: connected on pin 15, 14, 16, 10 but not programmed yet
Servo Motor: pin 6

I went to the website you sent and I found a download link in the ServoTimer2.o folder. Is this correct? :expressionless:
Also I realised it has been a few months since last uploading a library... I'm sorry, could you explain how to do that?

We aren't able to just add another battery pack as it wouldn't fit in the CanSat.

Then at the very minimum you need a decoupling filter to keep servo electrical noise out of the Arduino and sensor power.

Otherwise, Murphy's Law guarantees that the Arduino will fail when the servo starts to move, but not on the bench, just while in flight :wink:

A typical power supply decoupling filter is shown below. You might need to optimize R and C values -- there is plenty of literature on the topic.

Some decoupling filter designs include a diode to protect the critical circuitry against severe voltage drops, such as when the servo draws the stall current (which is every time it starts to move).

decouple.png

decouple.png

100µF is small for drop-out suppression like this(*), start at 1000µF or more perhaps. Using a
schottly diode rather than a 47 ohm resistor will prevent the cap discharging back through
the servo too.

(*) The Uno already have this sort of capacitance on board I believe.

And you still haven't said what your battery is.

Steve

small for drop-out suppression

Read the read of the post.

Okay so our battery isn’t as easy as we’d hoped but here it comes…
We attached 2 Lithium Polymer batteries to eachother. One is 2000 mAh and the other is 380 mAh. (both 3.7 V)
We wired the endings of the batteries so that we have 2 circuits. ( I just realised I’ve spelled circuits wrong all along)
One circuit now has 3.7 V and the other has 2 * 3.7 V = 7.4 V
The 7.4 V circuit will be converted into 5 V using this little voltage converter that I’d never seen before.
Anyways, the arduino will be powered on 5 V and the 3.7 V will be used on a camera not mentioned before.

From what I’ve heard I think what I understand is that the servo should be directly connected to the 5 V loop with the attach pin still on the arduino obviously and I should be using the <ServoTimer2.h> library. (correct me if i’m wrong)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.