![]() | ![]() | ![]() | ![]() |
Servos
|
Diagram | Servo | Test Sketch | Servo Test |
I'll be using MG996 servos for DC automation, because they are relatively hi-torque and I am familiar with them. I'll mount the servo on the side of the updraft valve on a 3/16" thick piece of plywood. Please check out the diagram.
A while back I bought a roll of steel wire (9 AWG) from Lowes, this would make great actuator rods (linkage) for the updraft valves. I'll weld a 3mm x 10mm machine screw to the end of (at 90°) to thread into the actuator arm. I know that'll be ugly, I don't weld often enough to be good, but it should work. When the servo arm rotates, about 180°, as it moves the valve control arm, the 3mm bolt will thread or unthread about 1/2 a revolution, and move up and down .25mm which shouldn't be a problem. I'm going to start with a 9" long straight piece of 9 AWG wire and bend it a little long, Then put a slight kink in it to match the servo/valve. Starting at the welded bolt, the first bend 90° down will be 3" from the weld, enough to miss the mount board when the arm is to the right (valve closed). The second bend 90° up will be under the 1/4" hole in the control arm.
Remember, as in all servo applications, you must be sure the servo is at a known point in it's rotation before attaching the activator arm, I centered all mine and installed the arm straight down when the servo was centerd. The arms swing from left, dowm, and to the right or vise versa. I set up a servo setting program in the control system so I could easily find and mark the program values for each servo postion (open, closed). Once I have determined the open/close programmed value, I'll put that in the program's VlvOpnCls[][] array.
When I manually started tool #8 (DW735 Planer), using the data terminal keypad, it worked great but when I connected Isnsr 8, and tried auto mode (start the planer's motor), the valve wouldn't open all the way. I realized when you turn on the DW735 Planer (to autostart the DC) it's chip ejector blows so hard, out the dust port and into the updraft valve, the servo, trying to open the valve's flapper, was working against this force. I'm going to have to do some testing to find out how much power I need to open this valve under pressure. Possibly a tougher servo and longer horn or a completely new 4" slide valve. Or think of a better way to do this!
![]() |
One of the MG996 servos with a actuator arm ("horn") installed. |
![]() |
Another view. This is more or less how it will be mounted. |
![]() |
A servo and it's mounting board. |
![]() |
Roll of 9 AWG steel wire from Lowes. |
![]() |
Cutting off 9" segments of more or less straight wire. |
![]() |
Wire segments with 3mm bolt (ugly)welded on the end. Note the two black marks on the bottom piece, they are the first two bends. |
![]() |
Wire linkage bent and threadded onto a servo actuator arm (aka. horn). |
![]() |
Most linkages installed. |
/*********************************************************************** Adafruit 16-channel PWM Servo driver PCA9685, 2004 LCD TOGGLE BETWEEN LEFT AND RIGHTD SERVO (180 deg.) ClOSED = ARM RIGHT THIS SKETCH SHOULD WORK WITH EITHER THE ARDUINO DATA TERMINAL OR IDE ************************************************************************/ #include <Wire.h> #include <Adafruit_PWMServoDriver.h> /************************** DEFINES ************************************/ #define SERVOADDR 0X40 // SECONDARY ADDR: 0X41 // SERVO FREQ: 50Hz = 20MS/cycl, 2MS / 4096 = 4.882 US/incr #define SERVO_FREQ 50 // ANALOG SERVOS RUN AT 50 Hz UPDATES #define CLRDLY 200 // CLEAR SCREEN DELAY 200MS #define HI 1 #define LO 0 #define LEFT 160 #define RIGHT 480 #define SPLAT '*' #define NL 10 #define BS 8 #define SPC 32 #define ROWMAX 4 #define COLMAX 20 #define DSPDLY 500 // DISPLAY TIME Ms #define IDLE 0 #define MLEFT 1 #define MRIGHT 2 #define INSTRMAX 100 // #define DEBUG 1 /************************** VARIABLES ************************************/ Adafruit_PWMServoDriver Servo = Adafruit_PWMServoDriver( SERVOADDR ); short Left = LEFT, Right = RIGHT; long NxtDspl = 0; // NEXT TIME BUTTON DEBOUNCE byte MinMax = 0; // LEFT/RIGHT CONTROL bool KeyAvail = false; char InStr[INSTRMAX]; byte InNdx = 0, ChrNdx = 0, Mode = IDLE; char PosCur[8] = { ESC,'[','0',';','0','0','f',0};// POSITION CURSOR, ROW,COL char ClrScrn[6] = { ESC,'[','2','j',0}; /************************** PROTOTYPES ************************************/ void srvoLft( uint8_t num); void srvoRt( uint8_t num); char getChr(); void cancel(); void posCur( byte row, byte col ); /*F****************************************************************** * **********************************************************************/ void setup() { Serial.begin( 9600 ); Serial.print( " Servo Test"); Servo.begin(); Servo.setPWMFreq( SERVO_FREQ ); // ANALOG SERVOS RUN AT ~50 Hz UPDATES NxtDspl = millis() + DSPDLY; // CAPTURE TIME memset( InStr, 0, sizeof( InStr )); // CLEAR ASCII BUF delay( 500 ); } /*F****************************************************************** * **********************************************************************/ void loop() { long now; char chr; if( KeyAvail ) { chr = getChr(); switch( chr ) { case '0': // CANCEL CURRENT OPERATION cancel(); break; case '4': // LEFT MODE Mode = LEFT; posCur( 2, 0); Serial.print( "Left: " ); break; case '6': // RIGHT MODE Mode = RIGHT; posCur( 2, 0); Serial.print( "Right: " ); break; case '2': // INCREMENT SERVO VALUE if( Mode = MLEFT ) Left += 5; else if( Mode = MRIGHT ) Right += 5; srvoLft( 1 ); break; case '8': // DECREMENT SERVO VALUE if( Mode = MLEFT ) Left -= 5; else if( Mode = MRIGHT ) Right -= 5; srvoRt( 1 ); break; } } now = millis(); if( now > NxtDspl ) { NxtDspl = millis() + DSPDLY; // CAPTURE TIME switch( Mode ) { case IDLE: return; case MRIGHT: posCur( 1, 9 ); Serial.print( Right ); srvoRt( 1 ); break; case MLEFT: posCur( 1, 9 ); Serial.print( Left ); srvoLft( 1 ); break; } } delay( 500 ); // WAIT 1/2 SEC } /*F****************************************************************** * GET CHAR FROM INSTR **********************************************************************/ char getChr() { // RUNS EACH TIME (AFTER) LOOP RUNS char chr; if( (KeyAvail != true) || (InNdx == 0) ) return( 0 ); if( ChrNdx < InNdx ) { chr = InStr[ChrNdx]; InStr[ChrNdx++] =0; return( chr ); } KeyAvail = false; InNdx = ChrNdx =0; return( 0 ); } /*F****************************************************************** * CANCEL CURRENT OPERATION **********************************************************************/ void cancel() { Mode = IDLE; } /*F******************************************************************* * **********************************************************************/ void srvoRt( uint8_t num) { int val; val = Right; posCur( 1, 10 ); Serial.print((String)"Right " + ", val = " + val); Servo.setPWM( num, 0, val); delay( 100 ); } /*F******************************************************************* * **********************************************************************/ void srvoLft( uint8_t num) { int val; val = Left; posCur( 0, 2 ); Serial.print("Left, val = " + (val +0x30) ); Servo.setPWM( num, 0, val); delay( 100 ); } /*F****************************************************************** * RS-232 INTERRUPT SERVICE ROUTINE, DO NOT TARRY HERE **********************************************************************/ void serialEvent() { // RUNS EACH TIME (AFTER) LOOP RUNS char chr; while( Serial.available()) // INTERRUPT SERVICE ROUTINE, DON'T TARRY HERE { chr = (char)Serial.read(); // GET NEW CHAR if( (chr != NL) && (chr < 32) ) continue; // DISCARD NON_PRINTABLE CHAR InStr[InNdx++] = chr; // ADD NEW CHAR TO InStr[] KeyAvail = true; // SET FLAG SO MAIN LOOP CAN DO PROCESS CHAR if( InNdx >= INSTRMAX ) { // IN STR NDX TOO LARGE, RESET IT InNdx =0; break; } } } /*F****************************************************************** * POSITION CURSOR Esc[r;ccf SET CURSOR TO ROW COL **********************************************************************/ void posCur( byte row, byte col ) { char str[8]; strcpy( str, PosCur ); sprintf( &str[2], "%1d;%02df", row, col ); Serial.print( str ); delayMicroseconds( 200 ); }
![]() |
|