Valve4 Program
Back to Valve4

This will be slaved to the DustAuto system via RS232.   DustAuto will send one letter commands followed by a NL, the valve controller will respond with "OK\n" when the move is complete or "Fail\n" if the move timed out.   I used the DustSensor2 sketch as a starting place, since this has to do some similar things.    

At startup, move the valve in the closed direction until the closed limit switch is in the HIGH condition.   This way, I'll have a known starting point for slider travel.   Normal valve movement will step in open/close direction until the appropriate limit swich goes high.   I originally tried the AccelStepper lib, but it is very noisy and slow.    
Open and close requests will be slow, about 2.5sec.        

I don't need any holding torque (slider holds it's own position), so I am disabling the driver (ENAB low) when not moving the valve slider.    

The limit switches use digital inputs with a pullup and the NC input will short to ground until the limit is reached and the switch opens.   When the switch opens, the Nano will see a low to high transition.   The print statements in the code were used when testing with the Arduino IDE, I used the timestamps to determine open/close times.   The Serial.printlns in the valve open/close calls are commented out, when connected to the DustAuto system.  

When the slider starts to move, there is much more resistance.   So I made the opnVlv() clsVlv() pulse the stepper slower (1100Hz) for SLOWAT (1200) pulses then go to the faster pulses (2854) until the limit switch is pushed.   The slower pulse rate yeilds the peak torque of the stepper motor.
I had to comment out the opnVlv change to faster since the valve is under a lot of pressure from the planer, and remain in the hi torque mode.        

/*H******************************************************************
* Valve4
* Nema-17 STEPPER MOTOR (17HS16-2004S1) 45Ncm(64OzIn) WITH DRV-8825 DRIVER
* I ALSO HAVE A 17HS19-2004S1 59Ncm(84OzIn) IF I NEED THE EXTRA TORQUE
REFERENCED IN DUSTAUTO AS Valve-8
(CW = CLOSE, CCW = OPEN, FROM MOTOR BACKEND)
Blk  A+   Coil-1         I'M STARTING OUT THINKING CW WILL CLOSE VALVE
Grn  A-   Coil-1
Rdd  B+   Coil-2
Blu  B-   Coil-2
**********************************************************************/
#include <SoftwareSerial.h>

/************************** DEFINES ************************************/
// REVERSED MEANING DRIVER PINS: SLEEP* = ENAB, FAULT* = DRVOK
#define DRVOK      4                                   // DRV OK, WAS FAULT*
#define ENVRX      3                                           // ENV RX PIN
#define ENVTX      2                                           // ENV TX PIN
#define STEP       5                                         // DRV STEP PIN
#define DIR        6                  // DIRECTION PIN, HI = FWD (CLOCKWISE)
#define ENAB       9                               // DRV ENABLE, WAS SLEEP*
#define OPNLIM     7                                    // OPEN LIMIT SWITCH
#define CLOSLIM    8                                   // CLOSE LIMIT SWITCH
#define ENVWAT     2000                          // ENV SERVER MAX RESP TIME
#define ENABTIM    1700                                    // ENABLE TIME US
#define HLFSTP     10                                      // HALF STEP MODE
#define NL         10
#define OK         1
#define ERR        -1 
#define FAIL       -1 
#define OPEN       LOW                                                 // CW
#define CLOS       HIGH                                               // CCW
#define TIMHI      50                        // US STEPPER PULSE HI CONSTANT
#define TIMLO1     859                   // US STPPR PULSE LO 1 FREQ: 1100Hz
#define TIMLO2     300                   // US STPPR PULSE LO 2 FREQ: 2857Hz
#define SLOCNT     1200                          // STEPPER PULSE SLOW COUNT
typedef unsigned long ulong;

/************************** VARIABLES ************************************/
SoftwareSerial Env( ENVRX, ENVTX );
bool Rs232 = false;                                       // RS232 DATA FLAG
char RsData[32], EnvBuf[32];                                   // RS232 DATA
byte RsNdx =0;      //     CW <0     CCW >0                 RS232 DATA INDEX
byte EnvNdx =0;
byte Status =0;

/************************** PROTOTYPES ************************************/
short   clsVlv();
int     doReq();
short   opnVlv();
short   getEnv( char req );                         // REQ IS UC LETTER 'T'
short   recal();
void    serialEvent();

/*F******************************************************************
*
**********************************************************************/
void 
setup() 
{
    Serial.begin( 9600 );
    Env.begin( 9600 );
    pinMode( DRVOK, INPUT );                       // SET DRIVER OK INPUT PIN
    pinMode( OPNLIM, INPUT_PULLUP);        // SET OPEN LIMIT SWITCH INPUT PIN
    pinMode( CLOSLIM, INPUT_PULLUP);      // SET CLOSE LIMIT SWITCH INPUT PIN
    pinMode( LED_BUILTIN, OUTPUT);               // SET BUILT IN LED AS OUPUT
    pinMode( STEP, OUTPUT);                            // DECLARE OUTPUT PINS
    pinMode( DIR, OUTPUT);
    pinMode( HLFSTP, OUTPUT);
    digitalWrite( HLFSTP, HIGH );          // PUT DVR8825 INTO HALF STEP MODE
    memset( RsData, 0, sizeof( RsData ));                   // CLEAR REQ BUFF
    recal();                                 // MOVE VALVE TO CLOSED POSITION
}
/*F******************************************************************
*
**********************************************************************/
void 
loop() 
{
    if( Rs232 )
        doReq();
    delay( 100 );
}
/*F******************************************************************
* RECALIBRATE, LIKE A DISK DRIVE, FIND VALVE'S CLOSED POSTION
**********************************************************************/
short 
recal() 
{
 // Serial.println((String)"recal");
    return( clsVlv());
}
/*F******************************************************************
* RS-232 INTERRUPT SERVICE ROUTINE, DON'T TARRY HERE
**********************************************************************/
void
serialEvent()
{                                                    // RUNS AFTER EACH LOOP
    int       val;
    char   chr;

    if( Serial.available())
    {
        while( Serial.available())                 // HDW SERIAL CHARS AVAIL
        {
            chr = (char)Serial.read();                       // GET NEW CHAR
              if( (chr < 32) && (chr != NL) )
                  continue;                // DISCARD NON-NEWLINE CONTROL CHAR
            RsData[RsNdx++] = chr;               // ADD NEW CHAR TO RsData[]
            if( chr == NL )
            {
                Rs232 = true;                      // SET FLAG FOR MAIN LOOP
                return;
            }
        }
    }
}
/*F******************************************************************
*
**********************************************************************/
int     // COMMANDS FROM DUSTAUTO SYSTEM ARE SINGLE LETTERS FOLLOWED BY A NL 
doReq() 
{
    byte  ndx;
    char  cmd;

    digitalWrite( LED_BUILTIN, HIGH );
    for( ndx =0; (cmd = RsData[ndx++]) && (ndx <= RsNdx); )  
    {                        // PROCESS ALL CHARS IN THE INPUT BUFFER: RsData
        switch( cmd )
        {
            case NL:                                   // NEWLINE, END OF REQ
                Status = OK;
                break;
            case 'O':                                           // OPEN VALVE
                opnVlv();
                break;
            case 'C':                                          // CLOSE VALVE
                clsVlv();
                break;
            case 'R':                                          // RECALIBRATE
                recal();
                break;
            case 'I':                                    // SET CURRENT LIMIT
                digitalWrite( ENAB, HIGH );                  // ENABLE DRIVER
                break;
            case 'E':                                            // END TESTS
                digitalWrite( ENAB, LOW );                  // DISABLE DRIVER
                break;
            case 'T':                                         // TEMP/HUM REQ
                getEnv( 'T' );
                break;
        } // switch END
    }  // for END
    memset( RsData, 0, sizeof( RsData ));                 // CLEAR RS232 BUFF
    RsNdx = 0;                                                 // RESET RSNDX
    Rs232 = false;                                   // RESET DATA AVAIL FLAG
    digitalWrite( LED_BUILTIN, LOW );
}
/*F******************************************************************
* OPEN VALVE
**********************************************************************/
short
opnVlv() 
{        // SET TARGET POS = STEPS +CW FROM 0, -CCW FROM 0, 8000 = 40 REVS CW
    short  cnt;  //       ___  Hi
    ulong  end;
                     // __| |__ Lo
    Status = OK;
    digitalWrite( ENAB, HIGH );                              // ENABLE DRIVER
    delayMicroseconds( ENABTIM );                      // DRIVER WAKE UP TIME
    digitalWrite( DIR, OPEN );                                 // SET DIR CCW
    end = millis() + 5000;
    for( cnt =0; (digitalRead( OPNLIM ) == LOW) && (millis() < end) ; cnt++ )
    {                                // CONTINUE TILL OPEN LIMIT SWITCH IS HIT
        digitalWrite( STEP, HIGH);                // STEP PULSE TO DVR8825 HI
        delayMicroseconds( TIMHI );                 // STEP PULSE WIDTH 50 US
        digitalWrite( STEP, LOW);                 // STEP PULSE TO DVR8825 LO
//        if( cnt < SLOCNT )
              delayMicroseconds( TIMLO1 );   // PERIOD: 909 US, F: 1100Hz HITRQ
//        else
//            delayMicroseconds( TIMLO2 );   // PERIOD: 350 US, F: 2857Hz LOTRQ
      }                    // @ 400,400 = 2.5S, @ 300,400 = 2.1S, 300,300 = BAD
    digitalWrite( ENAB, LOW );                    // PUT DRIVER BACK TO SLEEP
    if( millis() >= end )
        Serial.println( "E" );                     // SEND RESULT TO DUSTAUTO
    else
        Serial.println( "OK" );                    // SEND RESULT TO DUSTAUTO
    Status = OK;
    return( OK );
}
/*F******************************************************************
* CLOSE VALVE
**********************************************************************/
short 
clsVlv() 
{        // SET TARGET POS = STEPS +CW FROM 0, -CCW FROM 0, 8000 = 40 REVS CW
    short  cnt;
    ulong  end;

// Serial.println((String)"clsVlv Bgn");
    Status = OK;
    digitalWrite( ENAB, HIGH );                                // WAKE DRIVER
    delayMicroseconds( ENABTIM );                      // DRIVER WAKE UP TIME
    digitalWrite( DIR, CLOS );                                  // SET DIR CW
    end = millis() + 5000;
    for( cnt =0; (digitalRead( CLOSLIM ) == LOW) && (millis() < end) ; cnt++ )
    {                              // CONTINUE TILL CLOSED LIMIT SWITCH IS HIT
        digitalWrite( STEP, HIGH);                // STEP PULSE TO DVR8825 HI
        delayMicroseconds( TIMHI );
        digitalWrite( STEP, LOW );                // STEP PULSE TO DRV8825 LO
        if( cnt < SLOCNT )
            delayMicroseconds( TIMLO1 ); // PERIOD: 909Us, FREQ: 1100Hz HITRQ
        else
            delayMicroseconds( TIMLO2 ); // PERIOD: 350Us, FREQ: 2857Hz LOTRQ
    }
    digitalWrite( ENAB, LOW );                    // PUT DRIVER BACK TO SLEEP
    if( millis() >= end )
        Serial.println( "E" );                     // SEND RESULT TO DUSTAUTO
    else
        Serial.println( "OK" );                    // SEND RESULT TO DUSTAUTO
    Status = OK;
    return( OK );
}
/*F******************************************************************
* SEND REQUEST TO Env SERVER, SEND IT'S RESPONSE TO DA 
* RETURN: 'A'- 'Z' OK, else ERR
**********************************************************************/
short
getEnv( char req )                              // REQ IS UC LETTER 'T'
{
    ulong  end;
    char   chr, resp =0;
    short  rtn = OK;

    Env.listen();
    Env.println((String)"T" );                   // SEND ENV SERVER REQUEST
    end = millis() + ENVWAT;           // SET TIMER FOR ENV SERVER RESPONSE
    memset( EnvBuf, 0, sizeof( EnvBuf ));
    for( EnvNdx =0; (millis() < end) ;   )
    {                         // LOOP HERE WHILE ENV SERVER DOES IT'S THING
        if( Env.available() )
        {                                  // KEEP READING TIL FIND NEWLINE
            chr = Env.read();          // GET RESPONSE: 'O' =OK, 'E' =ERROR
            if( chr == NL )
                break;
            EnvBuf[EnvNdx++] = chr;               // ADD NEW CHR TO INP BUF
        }
    }
    if( (rtn < 0) || (millis() >= end))
        Serial.println("Env failed");
    else
        Serial.println( (String)EnvBuf );
    return( rtn );
}