Asset shield cant move Servo?

I want to move a servo using the Asset shield.

I’ve setup a function, and call it, however nothing happens. The function returns the value provided for the angle, but the servo does not move.

The function is “sa” or ServoToAngle.

I had it setup on A1-A5, but it didnt work. Last try I’m doing is on D1, but no luck.

    // This #include statement was automatically added by the Particle IDE.
    #include <AssetTracker.h>

    /* -----------------------------------------------------------
    This example shows a lot of different features. As configured here
    it'll check for a good GPS fix every 10 minutes and publish that data
    if there is one. If not, it'll save you data by staying quiet. It also
    registers 3 Particle.functions for changing whether it publishes,
    reading the battery level, and manually requesting a GPS reading.
    ---------------------------------------------------------------*/

    // Getting the library

    // Set whether you want the device to publish data to the internet by default here.
    // 1 will Particle.publish AND Serial.print, 0 will just Serial.print
    // Extremely useful for saving data while developing close enough to have a cable plugged in.
    // You can also change this remotely using the Particle.function "tmode" defined in setup()
    int transmittingData = 1;
    int angle = 1;
    Servo myServoName;
    int pos = 0;


    // Used to keep track of the last time we published data
    long lastPublish = 0;

    // How many minutes between publishes? 10+ recommended for long-time continuous publishing!
    int delayMinutes = 10;

    // Creating an AssetTracker named 't' for us to reference
    AssetTracker t = AssetTracker();

    // A FuelGauge named 'fuel' for checking on the battery state
    FuelGauge fuel;

    // setup() and loop() are both required. setup() runs once when the device starts
    // and is used for registering functions and variables and initializing things
    void setup() {
        // Sets up all the necessary AssetTracker bits
        myServoName.attach( D1 );
        t.begin();
        
        // Enable the GPS module. Defaults to off to save power. 
        // Takes 1.5s or so because of delays.
        t.gpsOn();
        
        // Opens up a Serial port so you can listen over USB
        Serial.begin(9600);
        
        // These three functions are useful for remote diagnostics. Read more below.
        Particle.function("sa", servoToAngle);
        Particle.function("tmode", transmitMode);
        Particle.function("batt", batteryStatus);
        Particle.function("gps", gpsPublish);
        
    }

    // loop() runs continuously
    void loop() {
        // You'll need to run this every loop to capture the GPS output
        t.updateGPS();

        // if the current time - the last time we published is greater than your set delay...
        if(millis()-lastPublish > delayMinutes*60*1000){
            // Remember when we published
            lastPublish = millis();
            
            //String pubAccel = String::format("%d,%d,%d",t.readX(),t.readY(),t.readZ());
            //Serial.println(pubAccel);
            //Particle.publish("A", pubAccel, 60, PRIVATE);
            
            // Dumps the full NMEA sentence to serial in case you're curious
            Serial.println(t.preNMEA());
            
            // GPS requires a "fix" on the satellites to give good data,
            // so we should only publish data if there's a fix
            if(t.gpsFix()){
                // Only publish if we're in transmittingData mode 1;
                if(transmittingData){
                    // Short publish names save data!
                    Particle.publish("G", t.readLatLon(), 60, PRIVATE);
                }
                // but always report the data over serial for local development
                Serial.println(t.readLatLon());
            }
        }
    }

    // Allows you to remotely change whether a device is publishing to the cloud
    // or is only reporting data over Serial. Saves data when using only Serial!
    // Change the default at the top of the code.
    int transmitMode(String command){
        transmittingData = atoi(command);
        return 1;
    }

    int servoToAngle(String command){
        angle = atoi(command);
        myServoName.write(angle);
        return angle;
    }

    // Actively ask for a GPS reading if you're impatient. Only publishes if there's
    // a GPS fix, otherwise returns '0'
    int gpsPublish(String command){
        if(t.gpsFix()){ 
            Particle.publish("G", t.readLatLon(), 60, PRIVATE);
            
            // uncomment next line if you want a manual publish to reset delay counter
            // lastPublish = millis();
            return 1;
        }
        else { return 0; }
    }

    // Lets you remotely check the battery status by calling the function "batt"
    // Triggers a publish with the info (so subscribe or watch the dashboard)
    // and also returns a '1' if there's >10% battery left and a '0' if below
    int batteryStatus(String command){
        // Publish the battery voltage and percentage of battery remaining
        // if you want to be really efficient, just report one of these
        // the String::format("%f.2") part gives us a string to publish,
        // but with only 2 decimal points to save space
        Particle.publish("B", 
              "v:" + String::format("%.2f",fuel.getVCell()) + 
              ",c:" + String::format("%.2f",fuel.getSoC()),
              60, PRIVATE
        );
        // if there's more than 10% of the battery left, then return 1
        if(fuel.getSoC()>10){ return 1;} 
        // if you're running out of battery, return 0
        else { return 0;}
    }

For servos you need to go for PWM pins (https://docs.particle.io/reference/firmware/electron/#attach-)

(see also https://docs.particle.io/reference/firmware/electron/#analogwrite-pwm-)

But not all of these are free to use since the Asset Tracker already occupies some of them
see https://github.com/spark/shields/blob/master/electron-shields/asset-tracker/pdfs/asset-tracker-sch.pdf

Also make sure the servos used are not exceeding the power rating of the pins (max. 25mA per pin max. 120mA over all pins) and will run with the 3.7V of the LiPo (if not powered via USB)

Providing a full schematic of your setup and stating what servo you're using might also help :wink:

1 Like

So which pin should I use?

I changed the code to this, is it ok?

int servoToAngle(String command){
    angle = atoi(command);
    analogWrite(D1, angle);

    return angle;
}

D1 should be OK, but the question about the servo still stands.

You can also try writeMicroseconds()

Yeah, so the code does not work on D1.

So i’m guessing i’m doing something wrong with analogWrite?

I mean, even if the Pin is ok, the code does not work. Help!

Hi @r0b0tn1k

I am not sure that atoi works on Arduino-style Strings. Maybe you could try:

angle = command.toInt();

Your servo write command should be working with that.

@bko, OP said

I suppose the (const char*) cast overload of String takes care of that, but sure toInt() is preferable.

But we still don't know what servo and how it's wired (including the power supply)

Testing out .toInt() to see if that works.

In the meantime, the setup:
I have a micro servo, a Hitec HS-55 is what is says on the label.

It’s wired as such:
Black - Ground
Red - Vin
Yellow - D1.

No luck.

command.toInt() wasnt the culprit.

Here’s the thing that gets me. When I would wire this on the photon, even with the servo library it would work.

But even without code, just by plugging the servo in, it would not allow me to turn it. It would lock in.

On the Asset shield, it doesnt. I can turn it freely.

Btw, it’s powered by the included LiPo battery.

Ok, some progress:

I changed the vin pin to the 3.3v pin. Now it works.

However, the micro is now on all the time, I can hear the motor buzzing, and it’s going to fry it.

How do I avoid this?

You may want to call Servo.detach() after you’re done setting the position.

1 Like
myServo.detach();

will stop the signal to the servo, but you may also get some minor unwanted motion. re-attach() when you want to move again.

you likely need to review the timing of the PWM signal. As @ScruffR mentioned, you may want to look at writeMicroseconds() as an alternative to write() in order to get the timing correct and eliminate the buzzing.

1 Like

Now wait, I was using analogWrite, how are we switching back to Servo library again?

Hmm, what do you mean myServoName.write(angle); ?

Never mind, got it working with the servo library, i’m super happy! :slight_smile:

2 Likes