Using Actuator to Automate Open/Close of Computer Side Panel

Changing instances in that code of SERVO1PIN to servoPIN (2 instances, in definition and one somewhere else) I get:

Binary sketch size: 1,732 bytes (of a 5,310 byte maximum)

avrdude: error: usbtiny_transmit: usb_control_msg: sending control message failed, win error: A device attached to the system is not functioning.



avrdude: error: usbtiny_send: usb_control_msg: sending control message failed, win error: A device attached to the system is not functioning.

 (expected 64, got -5)

avrdude: error: usbtiny_receive: usb_control_msg: sending control message failed, win error: A device attached to the system is not functioning.

 (expected 4, got -5)
avrdude: verification error, first mismatch at byte 0x0000
         0x21 != 0x00
avrdude: verification error; content mismatch

And the red light on the trinket just flashes.

Okay, I have no idea why it works now, whatever, so here’s my code (basically just changed the slowspeed, dunno what fastspeed is for, but this is basically the code you posted, after i fixed the SERVO1PIN to servoPIN like I posted above)

/*******************************************************************
  As written, this is specifically for the Trinket although it should
  be Gemma or other boards (Arduino Uno, etc.) with proper pin mappings

  Trinket:        USB+   Gnd   Pin #0  Pin #1
  Connection:     Servo+  -    Servo1  Switch

 *******************************************************************/

#include <Adafruit_SoftServo.h>  // SoftwareServo (works on non PWM pins)

#define servoPIN 2        //Servo control line (orange) on Trinket Pin #0
#define SWitchPIN 3        //Momentary switch to ground when pushed to open/close door
#define posOpenCMD 130     //Define Clockwise Servo Limit in deg
#define posCloseCMD 0      //Define CounterClockwise Servo Limit in deg
#define fastTime 8000      //time to quickly open/close door, min of 3600 msec
#define slowTime 4000     //time to normally open/close door

boolean doorOPEN = false;  //initialize desired door state to closed

Adafruit_SoftServo myServo1;  //create a servo object

void setup() {
  // Set up the interrupt that will refresh the servo for us automagically
  OCR0A = 0xAF;            // any number is OK
  TIMSK |= _BV(OCIE0A);    // Turn on the compare interrupt (below!)

  //setup the IO pins
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);

  myServo1.attach(servoPIN);   // Attach the servo to pin 0 on Trinket

}

void loop()  {
  if (digitalRead(SWitchPIN) == LOW) { //see if switch is being pushed
    doorOPEN = !doorOPEN;              //reverse desired door state
    moveDoor(slowTime);                //call function to command the servo
  }
  delay(50);                           // waits 50 ms btw reads of switch
}

// We'll take advantage of the built in millis() timer that goes off
// to keep track of time, and refresh the servo every 20 milliseconds
// The SIGNAL(TIMER0_COMPA_vect) function is the interrupt that will be
// Called by the microcontroller every 2 milliseconds
volatile uint8_t counter = 0;
SIGNAL(TIMER0_COMPA_vect) {
  // this gets called every 2 milliseconds
  counter += 2;
  // every 20 milliseconds, refresh the servos!
  if (counter >= 20) {
    counter = 0;
    myServo1.refresh();
  }
}

// Function called whenever door is to be moved at a speed slower
// than normal servo speed. Interrupts work during this function but 
//button pushes will be ignored until motion is complete

void moveDoor(unsigned long time) {
  //compute the time needed to go 1 deg
  unsigned long Dlay = time / (posOpenCMD - posCloseCMD);
  //figure out if door is to be opened or closed
  if (doorOPEN == true) {
    //tell servo to go to open position, 1 deg at a time
    for (int pos = posCloseCMD; pos < posOpenCMD; pos++) {
      myServo1.write(pos);
      delay(Dlay);
    }
  }
  else {
    //tell servo to go to closed position, 1 deg at a time
    for (int pos = posOpenCMD; pos > posCloseCMD; pos--) {
      myServo1.write(pos);
      delay(Dlay);
    }
  }
}

The only problem is that when it’s uploaded, or when I unplug/replug USB, the servo quickly swings all the way 180* (let’s say closed ~10*, open ~150) and just buzzes there (i think it’s pressing up against my PSU). I hit the switch, and it swings all the way closed very quickly.

As in, if it was attached to the door, it would probably bring the hinges off quickly (which has happened MULTIPLE times, not in a while because I make sure before unplugging, replugging, uploading, etc).

Now, I plan to run off rechargeable battery and ideally the power will never shut off. BUT, should I put it into long term storage or something, or switch off the battery, it would do this. And uhh that’d be a nasty surprise, I probably wouldn’t even remember that it does that after such a storage.

I’m not sure why it’s doing that but I gotta fix that in the code. I’m pretty sure when the arduino micro was worked out where everything was all together, it didn’t do that.

I haven’t looked at the Adafruit’s servo library, but I know the more common servo library as a line of code that moves the servo to a position on setup. You might want to look through the library (usually in .h) to see if this is happening.

The bad part is that there is no way to tell the Arduino the last known position of the servo on boot up. If you know that every time the door will be closed when Arduino powers up or resets, you could input this value in the library and in theory, the servo should not move.

codlink:
The bad part is that there is no way to tell the Arduino the last known position of the servo on boot up. If you know that every time the door will be closed when Arduino powers up or resets, you could input this value in the library and in theory, the servo should not move.

The above is the problem. When you power down the MCU, it looses track of where the servo was last commanded. And once powered down and or reset, the MCU has no way to interrogate the servo to find out. When I did that bit of code I knew that the MCU would ASSume the door is shut when perhaps it was last left open and thus there would be a damn quick closing upon the 1'st button push. I didn't have a way to solve that. Now I think I do.

You can use the EEPROM to store the last commanded door position. And since EEPROM “wears out” I would use a ring of perhaps 100 locations to store that door position, cycling through the ring w/each door button push. Then, in setup(), the Arduino could read EEPROM and find the last door state (and position of the data in the ring) and thus know how to command the door upon button push. Now there would still be an ASSumption that you didn’t manually move the door and that it completed it’s last command but that’s the best you can hope for w/o some actual position feedback … perhaps at least 2 switches to let the MCU know if the door was fully open or fully closed. For that matter a continuous rotation servo (aka a gear motor) and 2 switches would have been easier.

I’m okay with the system assuming the door is shut when turned off, and coming back online (so servo position 10 degrees as I’m currently coding it). I wouldnt store the computer long term storage with the door open, or if I did, I’d take the door off the servo.

I also want to make sure there’s no jerky movements on turning back on, so even if the door is not closed or if it’s moved just a bit, it doesn’t jerk around. What happens now is that the servo jerks to 180* (bear in mind that open & close is 10* and 150* respectively so it always jerks), and then when I push the button, it jerks to close then slowMoves to open. Jerk = fullspeed movement.

I looked at Adafruit_SoftServo.h and saw nothing to indicate it being at some position on start or close:

// This is an ultra simple software servo driver. For best
// results, use with a timer0 interrupt to refresh() all
// your servos once every 20 milliseconds!
// Written by Limor Fried for Adafruit Industries, BSD license

#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif
 

class Adafruit_SoftServo {
 public:
  Adafruit_SoftServo(void);
  void attach(uint8_t pin);
  void detach();
  boolean attached();
  void write(uint8_t a);
  void refresh(void);
 private:
  boolean isAttached;
  uint8_t servoPin, angle;
  uint16_t micros;
};

Have you “fine tuned” the open and closed position commands ?

#define posOpenCMD 130     //Define Clockwise Servo Limit in deg
#define posCloseCMD 0      //Define CounterClockwise Servo Limit in deg

Do they need to be the 150 and 10 deg you mentioned ? Do I have them reversed ? If so then the moveDoor() code may need to change too.

Oh, right, I’m using 130/0 now because of a bit of fine tuning. You have it right, open=130, close=0, 4000 speed

OK, I’m a little confused as to what is happening when. Right now the code assumes the door is closed upon a reboot and/or power-up. No command is sent until the first button push. Then the code will “jerk” to the closed position and slowly open. After that initial “jerk” (and then really only if the door is not closed) there should be no jerking.

What happens now is that the servo jerks to 180* (bear in mind that open & close is 10* and 150* respectively so it always jerks), and then when I push the button, it jerks to close then slowMoves to open. Jerk = fullspeed movement.

So perhaps the jerk above is some power-up transient ? Would adding a command to closed position in the *setup()* help (see code below) ? I actually had one in there and then took it out. Lastly is it 0/130 closed/open or 10/150 ?
    /*******************************************************************
      As written, this is specifically for the Trinket although it should
      be Gemma or other boards (Arduino Uno, etc.) with proper pin mappings

      Trinket:        USB+   Gnd   Pin #0  Pin #1
      Connection:     Servo+  -    Servo1  Switch

     *******************************************************************/

    #include <Adafruit_SoftServo.h>  // SoftwareServo (works on non PWM pins)

    #define servoPIN 2        //Servo control line (orange) on Trinket Pin #0
    #define SWitchPIN 3        //Momentary switch to ground when pushed to open/close door
    #define posOpenCMD 130     //Define Clockwise Servo Limit in deg
    #define posCloseCMD 0      //Define CounterClockwise Servo Limit in deg
    #define slowTime 4000      //time to open/close door, min of 3600 msec

    boolean doorOPEN = false;  //initialize desired door state to closed

    Adafruit_SoftServo myServo1;  //create a servo object

    void setup() {
      // Set up the interrupt that will refresh the servo for us automagically
      OCR0A = 0xAF;            // any number is OK
      TIMSK |= _BV(OCIE0A);    // Turn on the compare interrupt (below!)

      //setup the IO pins
      pinMode(servoPIN, OUTPUT);
      pinMode(SWitchPIN, INPUT_PULLUP);

      myServo1.attach(servoPIN);     // Attach the servo to pin 0 on Trinket
      myServo1.write(posCloseCMD);     //command door to close after reset
    }

    void loop()  {
      if (digitalRead(SWitchPIN) == LOW) { //see if switch is being pushed
        doorOPEN = !doorOPEN;              //reverse desired door state
        moveDoor(slowTime);                //call function to command the servo
      }
      delay(50);                           // waits 50 ms btw reads of switch
    }

    // We'll take advantage of the built in millis() timer that goes off
    // to keep track of time, and refresh the servo every 20 milliseconds
    // The SIGNAL(TIMER0_COMPA_vect) function is the interrupt that will be
    // Called by the microcontroller every 2 milliseconds
    volatile uint8_t counter = 0;
    SIGNAL(TIMER0_COMPA_vect) {
      // this gets called every 2 milliseconds
      counter += 2;
      // every 20 milliseconds, refresh the servos!
      if (counter >= 20) {
        counter = 0;
        myServo1.refresh();
      }
    }

    // Function called whenever door is to be moved at a speed slower
    // than normal servo speed. Interrupts work during this function but
    //button pushes will be ignored until motion is complete

    void moveDoor(unsigned long time) {
      //compute the time needed to go 1 deg
      unsigned long Dlay = time / (posOpenCMD - posCloseCMD);
      //figure out if door is to be opened or closed
      if (doorOPEN == true) {
        //tell servo to go to open position, 1 deg at a time
        for (int pos = posCloseCMD; pos < posOpenCMD; pos++) {
          myServo1.write(pos);
          delay(Dlay);
        }
      }
      else {
        //tell servo to go to closed position, 1 deg at a time
        for (int pos = posOpenCMD; pos > posCloseCMD; pos--) {
          myServo1.write(pos);
          delay(Dlay);
        }
      }
    }

I think it was just wiring from usb, it all works and is great!

Door broke off so i have to reglue that on, computer is almost done now though. I do wish there was an even smoother code though, this actually is just a bunch of smaller jerks.

It’s fine, it’s installable and such, it’s just not as smooth as the varspeed.