|
|
|
|
| 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 );
}