![]() | ![]() | ![]() | ![]() |
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 ); }