System Board |
Data Terminal |
4" Updraft Valve |
4" Slider Valve |
This system uses the Arduino Data Terminal for displaying mode, tool being used, dust bin free space, and controlling the system. The 4" and 6" updraft valves make this system easy. Of the eight tools, only 6 use current sensors, the other 2 are run using manual mode.
The program Controls
| Default | Automatic Operation: The system polls I-sensors for each tool and if one increases (motor turned on) it opens the associated valve, and turns on the DC's blower. The system continues monitoring the current of the tool and if it's current returns to normal (motor off), the DC is shutdown and the tool's valve is closed. | |
| '1'-'8' | Manual operation: By entering a single digit 1-8, one of the tools is manually selected, the valve closed, and the DC started. If one of the tools is running in manual mode, and you enter another single digit 1-8 the DC shuts down, the valve is closed, the valve for the new machine is opened and the DC started again. | |
| '0' (zero) | Cancel any current operation, shuts down DC, close all valves. | |
| 'A' | Cycle All Vavles Cycle all valves (1-8) to clear any debris. | |
| 'B' | Open A SECOND Valve (Manual Mode) Request a tool number, then stop DC, open that tool's valve, restart the DC. | |
| '*' (splat) | Display Sensor Reading Requests a sensor number (1-8), when it is entered the sensor is selected and it's analog reading is displayed. Allows you to trurn on or off a machine and see it's Isnsr readings. | |
| '#' (crunch) | Set Servo Values Requests a valve number (1-8) then the valve is opened and the servo's digital value is displayed. Entering a '2' increases the digital setting, an '8' decreases the setting. Entering a '6' closes the valve and displays the servo's valve closed setting, again '2' and '8' increase and decrease the setting. Entering a '4' opens the valve and displays its servo setting. Sensors are polled when not in manual mode or one of the test modes, if one reads an analog reading equal or greater than RDGTHLD, the tools is activated, valve opened, and DC turned on. An analog read may return 1023 digital, with 5 volts max and a digital value of 0 - 1023 that means 5 / 1023 = .00488 mv / increment. RDGTHLD = 200, or 200 * .00488 = .976 volts at the sensor. |
If I decide I need more commands, I'll add a 'Test' mode (maybe letter 'B') which will have a menu of all test requests: cycle all valves, set servo open/close, display Isnsr readings, etc. The test mode is terminated by '0' (cancel) and while in 'Test' mode disable auto Isnsr scanning.
One thing to note about programming, I've not done a lot of Arduino programming but I have done a lot of 'C' code programming (I learned at Bell Labs many moons ago) so the sketches may not look quite like normal Arduino programming.
I'm not a big fan of the Arduino IDE editor, so I usually use my old friend, the ubiquitous vi, bounce the IDE, compile, and download.
Please note: CODING STYLE (Read this, it'll make the code easier to understand)
RS-232 Communication:
I am using RS-232 to communicate to the Data Terminal, Dust Detector, and Valve 8.
The Data Terminal will be on the hardware Serial, the other two will uses the Software Serial library.
Software Serial has a requirement that you can only listen to one serial port at a time and you must explicitly state which to listen to at any given time.
In order to make this work I am using a query/response scenario, the control system wil send a request then wait for a response from that remote.
That way I know which remote to listen to for response.
These query/response actions will each have a timeout associated, so a remote having a problem won't hang up the entire control system.
| After getting the basic system up and running, I converted the original dust detector to work with it (DustDetector2). The DustAuto System requests a dust depth from dust detector2 each second. | |
| Originally, | |
| DustDetector2 probes the dust in the bin, then transmitts (RS232 Ascii) the depth, in inches, to the DustAuto System. The Dust Collector System updates it's display of the current dust depth on the data terminal. Upon receiving the dust depth, DustAuto averages the last 5 readings before displaying or making a decision. If there have been 3 consecutive readings with the dust in the bin less than 8" from the top (where the sensor is) the system goes into "Dust Halt" mode and shuts down the dust collector blower motor. | |
| Now | |
|
The dust detector now uses an IR (Infra Red) device to dermine if the dust in it's bin is too high, base on a pot in the IR detector..
When queried by DustAuto the detector reports OK or FULL.
A cancel will restore the system to IDLE state and resume probing Isensors.
Averaging and requiring multiple sequential bad readings before halting, is due to the DustDetector looking down into a virtual tornado (chaos) in the dust bin while the system is running. | |
| If DustAuto doesn't receive a dust report within 30Ms, it shuts down ("Dust Halt"). | |
/***********************************************************************
DUST COLLECTION AUTOMATION:
PARTS TAKEN FROM BOB CLAGETT ON I LIKE TO MAKE STUFF (ILIKETOMAKESTUFF.COM)
I/O DEVICE: LCDKEYPAD (DATA TERM)
HDW: PCA9685 I2C PWM Servo driver, MG996R Servos, 74HC4051 Analog Mux,
CURRENT SENSOR: ACS712-30A (66Ms/A), AND A SOLID STATE RELAY
TOOLS NUMBERED 1 - 8, NO ZERO
***********************************************************************/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <SoftwareSerial.h>
/************************** DEFINES ************************************/
#define AUTODLY 20000 // AUTO MODE LOCK TIME
#define DCRUN 11 // DUST COLLECTOR GO PIN
#define DSPDLY 1000 // DELAY BETWEEN VOLT READING DISPLAYS
#define DUSTAVGCNT 5 // MUST HAVE DUSTAVGCNT RDNGS TO AVERAGE
#define DUSTBADS 3 // MUST HAVE DUSTBADS DUSTMINS TO HALT
#define DUSTCHK 1000 // TIME BETWEEN DUST REQUESTS
#define DUSTWAT 100 // TIME WAIT FOR DUST DTCTR
#define DUSTMIN 8 // DUST BIN MUST HAVE MORE THAN 8" SPACE
#define ESC 92 // BACKSLASH, IDE, Serial DOESN'T SEND CNTRL CHRS
#define INSTRMAX 32 // INSTRING SIZE
#define MITERSAW 6 // MITERSAW NBR
#define MUXS0 7 // LSB // ANALOG MUX SELECT 0
#define MUXS1 6 // ANALOG MUX SELECT 1
#define MUXS2 5 // MSB // ANALOG MUX SELECT 2
#define NBRTOOLS 8 // NUMBER OF TOOLS
#define NBRVALVES 8 // NUMBER OF VALVES
#define PWM_ADDR 0X40 // SERVO CONTOROL ADDRESS
#define V8WAT 5000 // PLANER VALVE WAIT TIME 5 SEC
#define RDGTHLD 200 // DIGITAL READING THRESHOLD @ 4.887 MV/INCR
#define DDRX 3 // SOFTWARE SERIAL RX
#define DDTX 4 // SOFTWARE SERIAL TX
#define V8RX 8 // VALVE-8 SERIAL RX
#define V8TX 9 // VALVE-8 SERIAL TX
#define SNSRDLY 20 // SAMPLE TIME 20MS
#define SRVODLY 525 // MG996R MVS 60deg in .17 SEC, SERVO ACT DELAY
#define SPINUP 1000 // DC SPIN UP TIME MS
#define SPINDOWN 3000 // DUST COLLECTOR SPIN DOWN TIME
#define SRVOBUMP 5 // VALVE SERVO INCR OR DECR
#define NL 10
#define OPN 0 // VALVE CCW
#define CLOS 1 // VALVE CW
#define ZIN A7 // SENSOR IN
enum Modes { IDLE, MANUAL, DSPRDG, AUTO, SETSRVO, MULTVLV, DUSTBINHALT };
typedef unsigned long ulong;
#define ssL(str,ndx) for( byte x = 0; x < ndx +1; x++ ) str[x] = str[x +1];
/************************** VARIABLES ************************************/
Adafruit_PWMServoDriver Servo = Adafruit_PWMServoDriver();
SoftwareSerial Dust( DDRX, DDTX ); // DUST DETECTOR SERIAL RX, TX
SoftwareSerial V8( V8RX, V8TX ); // PlanerValve (V8) SERIAL RX, TX
bool DcOnFlg = false, Rs232 = false, DstOnScrn = false;
bool V8Req = false;
char *ToolNam[NBRTOOLS+1] = { "0","Sander","BandSaw","Free-1","TableSaw"
,"Free-2","MiterSaw","Router","Planer" }; // TOOL NAMES ARRAY
short BasVal[NBRTOOLS +1], RdgTool = 0, VlvOc = CLOS;
int DustSpc, DustCnt =0, DustAcc =0, DustBads =0; // DUST RELATED VARS
int VlvVals[NBRVALVES +1][2] = {{0,0}, // OPN,CLOS VALVE, NO VALVE ZERO
{160,480}, {150,445}, {160,450}, {180,425}, {160,450},{125,435},{150,440}
// SANDER BANDSAW FREE-1 tableSAW FREE-2 MITERSAW ROUTER
,{190,465}, }; // MITERSAW
ulong NxtDsp =0, AutoTime =0, DustTim = 0;
char CurPos[8] = { ESC,'[','0',';','0','0','f',0}; // POSIT CURSOR, ROW,COL
char ClrScrn[6] = { ESC,'[','2','j',0}; // CLEAR SCREEN
char Hdr[] = {" Dust Collector\n"}, DstChrs[18];
char InStr[INSTRMAX], *VlvPos[2] = {"Open","Close"};
byte InNdx =0, Mode = IDLE, ActvTool = 0, ActVlv = 0, SsNdx =0;
/************************** PROTOTYPES ************************************/
void cancel( byte noPnt ); // CANCEL ALL OPERATIONS
bool chkAmpChg( int tool ); // CHECK FOR CURRENT CHANGE
void chkDustBin(); // PROCESS DUST BIN DEPTHS
void chkTools(); // CHECK FOR ACTIVE TOOL
void clrScrn(); // CLEAR DATA TERMINAL SCRN
void cycVlvs(); // CYCLE ALL VALVES
void dcOn(),dcOff(); // DUST COLLECTOR ON OFF
void dspDust( int dust ); // DISPLAY DUST STATUS
void dspIRdg( char chr ), dspIRdgSu(); // DISPLAY ISNSR READINGS
void doChrs(); // PROCESS KBD CHARS
void dustHalt( byte row, byte col, char* msg); // DUST HALT
char getChr(); // GET A CHAR FROM INSTR
int getDust(); // SOFTWARE SERIAL INTERRUPT SERVICE ROUTINE
void multVlv( char chr ), multVlvSu(); // OPEN MULTIPLE VALVES
short opnVlv( uint8_t num), clsVlv( uint8_t num, byte prnt); // OPN/CLOS VLV
void posCur( byte row, byte col ); // SET CURSOR POSTION
short reqV8( char cmd ); // SEND REQUEST TO PLANER VALVE
int rdSnsr( short snsr); // READ A SENSOR
void runTool( char chr ); // START A TOOL
void serialEvent(); // RS232 INTERRUPT ROUTINE
void setSrvo( char chr), setSrvoSu(); // SET SERVO VALUES
short v8Fail();
/*F******************************************************************
*
**********************************************************************/
void
setup()
{
int ndx;
Serial.begin( 9600 ); // START SERIAL I/O FROM DATA TERMINAL
Serial.print( Hdr ); // PRINT HEADER ON DATA TERM
Dust.begin( 9600 ); // START SFTW SERIAL I/O FROM DUST BIN
V8.begin( 9600 ); // START SFTW SERIAL I/O FROM DUST BIN
pinMode( DCRUN, OUTPUT); // I/O PIN OUTPUT FOR RUNNING DUST COLLECTOR
Servo.begin();
Servo.setPWMFreq( 50 ); // SET PWM FREQ = 50HZ
delay( 1000 );
pinMode( MUXS2, OUTPUT ); // DEFINE ANALOG OUTPUT TO MUX
pinMode( MUXS1, OUTPUT ); // DEFINE ANALOG OUTPUT TO MUX
pinMode( MUXS0, OUTPUT ); // DEFINE ANALOG OUTPUT TO MUX
for( ndx =1; ndx <= NBRTOOLS; ndx++)
BasVal[ndx] = rdSnsr( ndx ); // SAVE BASE SNSR RDGS, FOR VOLT CMPRSN
for( ndx =1; ndx <= NBRVALVES; ndx++)
clsVlv( ndx, 0 ); // CLOSE ALL VALVES
}
/*F******************************************************************
*
**********************************************************************/
void
loop()
{
if( Rs232 == true )
doChrs(); // CHAR ARRIVED ON THE SERIAL I/O FROM DATA TERM
if( millis() > DustTim )
chkDustBin(); // CHECK DUST BIN DEPTH
if( Mode == DUSTBINHALT )
return; // DUST BIN FULL, ONLY CANCEL WILL RESTART
chkTools(); // SEE IF ANY TOOL'S MOTOR IS RUNNING
if( (Mode == DSPRDG) )
dspIRdg( 9 ); // PASS CHAR TO DISPLAY ISNSR VOLTAGE
if( (Mode == SETSRVO) )
setSrvo( 9 ); // PASS CHAR TO ADJUST SERVO
}
/*F******************************************************************
* DUSTBIN DEPTH MESSAGE PROCESSING, AFTER DUSTAVGCNT
**********************************************************************/
void
chkDustBin()
{
int dust;
if((Mode == DSPRDG) || (Mode == SETSRVO))
return;
if( (dust = getDust()) < 0 )
return( dustHalt( 3, 0, " No Dust "));
if( (DustAcc > 0) && (DustCnt >= DUSTAVGCNT) )
{ // AVERAGE DUST DEPTH REPORTS FROM DETECTOR
DustSpc = DustAcc / DustCnt; // UPDATE DUST SPACE
dspDust( DustSpc );
DustCnt = DustAcc = 0; // RESET ACCUMULATOR AND COUNT
if( (DustSpc <= DUSTMIN) && (DustSpc > 0) && (DcOnFlg == true) )
{
if( (Mode == DUSTBINHALT) || (++DustBads < DUSTBADS) )
return; // ALREADY HALT MODE, OR NOT ENOUGH BAD DEPTHS
dustHalt( 0, 3, "Dust Bin Halt"); // DC RUNING & DUST BIN FULL
}
else
DustBads = 0; // ONE GOOD DUST READING RESETS DUSTBADS
}
}
/*F******************************************************************
* CHECK FOR TOOL MOTOR RUNNING
**********************************************************************/
void
chkTools()
{
int ndx, tool =0;
ulong now;
if( (Mode != AUTO) && (Mode != IDLE) )
return; // DO NOT CHECK FOR I FLOW UNLESS IN AUTO OR IDLE
now = millis();
for( ndx =1; ndx <= NBRTOOLS; ndx++)
{ // SCAN THROUGH TOOLS & CHECK FOR INCREASED CUR FLOW
if( chkAmpChg( ndx ))
{ // TOOL ON
tool = ndx;
Mode = AUTO;
if( tool == MITERSAW )
AutoTime = millis() + AUTODLY; // MITERSAW RUNNING
break; // FOUND ONE
}
}
if( (ActvTool == MITERSAW) && (now < AutoTime) )
return; // TOOL STARTED, WAIT AUTODLY B4 CHANGING
if( ActvTool == tool )
return; // SAME TOOL STILL RUNNING
if( ActvTool && !tool )
cancel( 0 ); // NO ACTIVE TOOL AND DC IS ON
else if( (tool != 0) && (tool != ActvTool) )
runTool( tool ); // START TOOL
}
/*F******************************************************************
* PROCESS KBD CHRS
* 0 CANCEL ALL
* 1-8 OPEN VALVE N, TURN DC ON
* A CYCLE ALL VALVES
* #n TEST ISNSRS
* *n SET SERVOS
**********************************************************************/
void
doChrs()
{
char chr;
while( (chr = getChr()) != 0 ) // READ A CHAR FROM InStr, IF AVAIL
{
Rs232 = false; // CLEAR SERIAL I/O FLAG
if( (Mode == DSPRDG) && (chr != '0'))
return( dspIRdg( chr ) ); // PASS CHR TO DSPLY ISENSOR VOLTS
if( (Mode == SETSRVO) && (chr != '0'))
return( setSrvo( chr )); // PASS CHR TO SERVO SETUP
if( (Mode == MULTVLV) && (chr != '0'))
return( multVlv( chr )); // PASS CHR TO MULTI VALVE SETUP
switch( chr )
{
case '0': // CANCEL CURRENT OPERATION
cancel( 0 );
break;
case 'A': // CYCLE ALL VALVES
cycVlvs();
break;
case 'B':
multVlvSu(); // OPEN MULTIPLE VALVES
break;
case '1' ... '8': // MANUAL MODE, OPEN VALVE & RUN DC
Mode = MANUAL;
runTool( chr );
break;
case '*': // SPLAT, DISPLAY ISENSOR VOLTAGE READING
dspIRdgSu();
break;
case '#': // CRUNCH, SETUP SERVOS
setSrvoSu();
break;
case NL: // GOT NEWLINE
break; // DISCARD NEWLINE
default:
Mode = IDLE;
break;
}
}
}
/*F******************************************************************
* SETUP FOR DISPLAY ISNSR VOLTAGE READINGS, CALLED FROM doChrs()
**********************************************************************/
void
dspIRdgSu()
{
if( DcOnFlg )
dcOff(); // DC IS RUNNING, STOP IT
Mode = DSPRDG; // SET DISPLAY READING MODE
AutoTime =0;
ActVlv = 0;
VlvOc = CLOS;
clrScrn();
posCur( 0, 2 );
Serial.print("Read Sensor");
posCur( 1, 0 );
Serial.print("Enter Tool Number");
}
/*F******************************************************************
* SETUP SERVO SETUP
**********************************************************************/
void
setSrvoSu()
{
if( DcOnFlg )
dcOff();
Mode = SETSRVO;
clrScrn();
delay( 200 );
posCur( 0, 0 );
Serial.print(" SERVO SETUP");
posCur( 1, 0 );
Serial.print("Enter Servo Number");
}
/*F******************************************************************
* RUN A MACHINE
**********************************************************************/
void
runTool( char chr )
{
byte tool;
clrScrn();
tool = (chr & 15); // STRIP OFF UPPER BITS OF CHR 0X3n
posCur( 0, 6 );
Serial.println( (String)ToolNam[tool] ); // ROW: 0, PRINT TOOL NAME
if( (ActvTool > 0) && (ActvTool != tool))
{ // NEW ACTIVE TOOL
if( DcOnFlg )
dcOff();
clsVlv( ActvTool, 1 );
}
ActvTool = tool;
opnVlv( ActvTool );
dcOn();
}
/*F******************************************************************
* CANCEL CURRENT OPERATION
**********************************************************************/
void
cancel( byte noPnt )
{
short ndx;
if( !noPnt )
{
clrScrn();
Serial.println(" Cancel Operation");
}
if( DcOnFlg )
dcOff(); // DC IS ON, STOP IT
for( ndx = 1; ndx <= NBRVALVES; ndx++ )
clsVlv( ndx, 1 ); // CLOSE ALL VALVES
Mode = IDLE;
AutoTime =0; // CANCEL ANY TOOL RUNNING IN AUTO MODE
RdgTool = ActvTool = 0;
if( noPnt )
return;
clrScrn();
Serial.print((String)Hdr );
}
/*F******************************************************************
* DISPLAY ISNSR VOLTAGE READINGS, CALLED FROM loop(), or doChrs()
**********************************************************************/
void
dspIRdg( char chr )
{
short tool, val;
int32_t now;
if( (chr >= '1' ) && (chr <= '8' ))
{ // SET NEW TOOL
RdgTool = (chr & 0X0F); // STRIP OFF 0X3n
posCur( 1, 0 ); // CLEARS ROW 1
Serial.print( (String)ToolNam[RdgTool] + " = " );
NxtDsp = 0; // FORCE IMMEDIATE DISPLAY
}
now = millis(); // GET CURRENT TIME
if((now > NxtDsp) && (RdgTool != 0))
{ // TIME TO DISPLAY A CURRENT READING
NxtDsp = (now + DSPDLY); // SAVE TIME OF CURRENT DISPLAY
val = rdSnsr( RdgTool );
posCur( 1, 10 ); // ROW 1, COL 10
Serial.println( val ); // 4.88MV / INCR
}
}
/*F******************************************************************
* CYCLE ALL VALVES TO REMOVE ANY LARGE SPLINTERS ETC.
**********************************************************************/
void
cycVlvs()
{
char tool, chr, buf[24];
clrScrn();
Serial.println(" Cycling Valves ");
if( DcOnFlg )
dcOff();
for( tool = 1; tool <= NBRVALVES; tool++ )
{ // FLAP ALL VALVES
posCur( 1, 0 ); // ROW 2, COL 0
Serial.println((String)ToolNam[tool] );
opnVlv( tool );
delay( SRVODLY ); // WAIT FOR THE SERVO TO ACT
clsVlv( tool, 1 );
delay( SRVODLY ); // WAIT FOR THE SERVO TO ACT
}
ActvTool = 0;
clrScrn();
Serial.print( Hdr );
}
/*F******************************************************************
* SERVO SETUP
**********************************************************************/
void
setSrvo( char chr )
{
short tool, val, rtn;
int32_t now;
if( !ActVlv && (chr == 9))
return; // CALLED FROM LOOP, NO ACTIVE VALVE
if( !ActVlv && ((chr >= '1') && (chr <='8')))
{ // NEW SERVO NMBR
ActVlv = chr & 15; // SET NEW ACTIVE VALVE NBR
posCur( 1, 0 ); // CLEARS ROW 1
Serial.print( (String)ToolNam[ActVlv] + "-" ); // LIKE "TableSaw-"
NxtDsp = 0; // FORCE IMMEDIATE DISPLAY
}
else if( (chr >= '1') && (chr <= '8') )
{
switch( chr )
{
case '2': // VAL UP
VlvVals[ActVlv][VlvOc] += SRVOBUMP;
break;
case '4': // OPEN VALVE
VlvOc = OPN; // VlvOc: VALVE SHOULD BE OPEN OR CLOSED
break;
case '6': // CLOSE VALVE
VlvOc = CLOS; // VlvOc: VALVE SHOULD BE OPEN OR CLOSED
break;
case '8': // VAL DN
VlvVals[ActVlv][VlvOc] -= SRVOBUMP;
break;
default:
break;
}
if( (ActVlv == 8) && (VlvOc == OPN) && ((rtn =reqV8( 'O' )) <0))
v8Fail();
else if( (ActVlv == 8) && (VlvOc== CLOS) && ((rtn =reqV8( 'C' )) <0))
v8Fail();
else
{
Servo.setPWM( ActVlv, 0, VlvVals[ActVlv][VlvOc]); // SET SERVO
delay( SRVODLY ); // WAIT FOR SERVO TO ACT
}
NxtDsp = 0; // FORCE IMMEDIATE DISPLAY
}
now = millis(); // GET CURRENT TIME
if((now > NxtDsp) && (ActVlv != 0))
{
NxtDsp = (now + DSPDLY); // SAVE TIME OF NEXT DISPLAY
posCur( 1, 10 ); // ROW 1, COL 10
val = VlvVals[ActVlv][VlvOc];
Serial.println( (String)VlvPos[VlvOc] + ":" +val ); // "Close: 450"
}
}
/*F******************************************************************
* TURN DUST COLLECTOR ON
**********************************************************************/
void
dcOn()
{
if( Mode == DUSTBINHALT )
return;
digitalWrite( DCRUN, 1);
posCur( 1, 13 );
Serial.println("DC On ");
DcOnFlg = true;
DustCnt = DustAcc = 0; // RESET DUST ACCUM & CNT
delay( SPINUP );
}
/*F******************************************************************
* TURN DUST COLLECTOR OFF
**********************************************************************/
void
dcOff()
{
posCur( 1, 3 );
Serial.println("Stopping DC ");
delay( 2000 ); // WAIT FOR PLENUM/HOSE TO EMPTY
digitalWrite( DCRUN, 0);
delay( SPINDOWN ); // WAIT FOR DC SPINDOWN
posCur( 1, 0 ); // ERASE ROW 1 TO END OF LINE
DcOnFlg = false;
}
/*F******************************************************************
* SAMPLING CURRENT SENSOR 1-7 (LO NIBBLE 0X0001 - 0X0111), SNSR 8 =0
**********************************************************************/
int
rdSnsr( short snsr ) // SNSR: 1 - 8
{
int rdVal, cnt, pin, msk =1, rtn;
ulong end, tmp;
// S0:D7(LSB), S1:D6, S2:D5(MSB) pin scans 7 - 5
for( pin = MUXS0, msk = 1; pin > 4; --pin, msk <<=1 )
{ // SET SENSOR # INTO MUX SEL0-SEL2 INPUTS, LSB to MSB, SNSR 8 = 0
if( msk & snsr )
digitalWrite( pin, HIGH ); // WT HI PINS MUXS0,MUXS1,MUXS2
else
digitalWrite( pin, LOW ); // WT LOW PINS MUXS0,MUXS1,MUXS2
}
delay( 2 ); // WAIT 2MS FOR SEL TO INP TIME
end = millis() + SNSRDLY; // SAVE CURRENT TIME + SAMPLE TIME
for( cnt = tmp =0; millis() < end; cnt++ )
{ // NOISY SIGNAL, AVERAGE FOR SAMPLE TIME
rdVal = analogRead( ZIN ); // 0-1023 DIGITAL RDG
tmp += rdVal;
} // 175 - 180 samples IN 20 MS
rtn = tmp / cnt;
return( rtn );
}
/*F******************************************************************
* CHECK FOR AMPERAGE CHANGE ON A TOOL
**********************************************************************/
bool
chkAmpChg( int tool)
{
int rdg;
rdg = rdSnsr( tool ); // READINGS RUN FROM OFF: 52-81, ON: 364-461
if( rdg > RDGTHLD ) // NEW SENSOR IGNORE BASE (BasVal[tool] + RDGTHLD))
return( true ); // RETURN TOOL ON
else
return( false ); // RETURN TOOL OFF
}
/*F******************************************************************
* GET CHAR FROM INSTR
**********************************************************************/
char
getChr()
{
char chr;
if( InNdx == 0 )
return( 0 );
chr = InStr[--InNdx];
ssL( InStr, InNdx ); // SHIFT INSTR LEFT
if( InNdx == 0 )
Rs232 = false; // INSTR EMPTY
return( chr );
}
/*F******************************************************************
* CLOSE A VALVE
**********************************************************************/
short
clsVlv( uint8_t num, byte prnt )
{
short rtn = 1;
if( DcOnFlg )
dcOff();
VlvOc = CLOS; // SET CURRENT VALVE POSTION = CLOSED
if( prnt )
{
posCur( 1, 0 );
Serial.println((String)"Vlv "+num+" Clos" );
}
if( num == 8 )
rtn = reqV8( 'C' ); // REQUEST VALVE 8 CLOSE
else
{
Servo.setPWM( num, 0, VlvVals[num][CLOS]); // CLOSE VALVE
delay( SRVODLY ); // WAIT FOR SERVO TO ACT
}
Servo.setPWM( 15, 0, 400 ); // DISTRACT PCA9685 TO SERVO 15
ActVlv = 0;
if( prnt )
posCur( 1, 0 ); // CLEAR ROW 1
}
/*F******************************************************************
* OPEN A VALVE
**********************************************************************/
short
opnVlv( uint8_t num )
{
int rtn = 1;
if( DcOnFlg )
dcOff();
VlvOc = OPN;
posCur( 1, 0 );
Serial.println((String)"Vlv "+num+" Opn");
if( num == 8 )
rtn = reqV8( 'O' ); // REQUEST VALVE 8 OPEN
else
{
Servo.setPWM( num, 0, VlvVals[num][OPN]); // OPEN VALVE
delay( SRVODLY );
}
ActVlv = num;
}
/*F******************************************************************
* RS-232 INTERRUPT SERVICE ROUTINE, DO NOT TARRY HERE
**********************************************************************/
void
serialEvent()
{ // RUNS EACH TIME (AFTER) LOOP RUNS
int val;
char chr;
while( Serial.available()) // INTERRUPT SERVICE ROUTINE, DON'T TARRY HERE
{
chr = (char)Serial.read(); // GET NEW CHAR
if( chr < 32 )
continue; // DISCARD NON_PRINtable CHAR
if( InNdx >= INSTRMAX )
{ // IN STR NDX TOO LARGE, RESET IT
Serial.println("Overrun");
break;
}
val = chr & 15;
InStr[InNdx++] = chr; // ADD NEW CHAR TO InStr[]
Rs232 = true; // SET FLAG SO MAIN LOOP CAN DO SOMETHING ABOUT IT
}
}
/*F******************************************************************
* REQUEST DEPTH FROM DUST DETECTOR, WAIT FOR RESPONSE
* DATA FROM THIS MAKES SERIOUS DECISIONS ABOUT SHUTING DOWN DC
**********************************************************************/
int
getDust()
{ // @ 9600 CHARS ARRIVE EVERY 1Ms
int val, dstVal;
char chr;
ulong end;
// Serial.println((String)"getDust: Bgn");
Dust.listen();
Dust.print( "D\n" ); // SEND DUST DEPTH REQUEST TO DUST DET
DustSpc = 0;
DustTim = millis() + DUSTCHK; // SET TIME OF NEXT DUST DEPTH REQUEST
val = dstVal =0; // BELOW: < DustTim IN CASE DUSTDET DOESN'T RESPOND
end = millis() + DUSTWAT; // SET TIMER FOR DUST DET RESONSE
while( millis() < end )
{ // LOOP HERE WHILE DUSTREQ & NOT DUSTTIME
if( Dust.available() )
{ // KEEP READING TIL FIND NEWLINE
chr = Dust.read(); // GET NEW CHAR
// Serial.println((String)"GotChr: "+chr);
if( chr == '\n' )
{ // END OF TRANSMISSION
DustAcc += dstVal; // ACCUMULATE DUST DEPTH
DustCnt++; // BUMP DUST READING COUNTER
break;
}
if( (chr < '0') || (chr > '9'))
continue; // DISCARD NON NUMERIC CHAR
val = (chr & 15); // CONVERT ASCII TO BIN: '2' (0X32) & 0X0F = 2
dstVal = (dstVal * 10) + val; // ACCUM DEC DUST DEPTH VALS
}
}
// Serial.println((String)"getDust: End, dstVal: "+dstVal);
if( millis() > end )
return( -1 );
return( dstVal );
}
/*F******************************************************************
* DUST HALT
**********************************************************************/
void
dustHalt( byte row, byte col, char *msg)
{
// DC RUNING & DUST BIN FULL, STOP EVERYTHING
Mode = DUSTBINHALT; // ADVERTISE WHY WE'RE SHUTDOWN
clrScrn();
posCur( row, col ); // SET CURSOR POSTION
Serial.println( (String)msg );
cancel( 1 ); // STOP EVERYTHING
}
/*F******************************************************************
* OPEN MULTIPLE VALVE SETUP
**********************************************************************/
void
multVlvSu()
{
if( DcOnFlg )
dcOff();
Mode = MULTVLV;
clrScrn();
delay( 200 );
// posCur( 0, 0 );
// Serial.print("OPEN ANOTHER VALVE");
posCur( 1, 0 );
Serial.print("Enter Valve Number");
dcOff();
}
/*F******************************************************************
* OPEN MULTIPLE VALVES
**********************************************************************/
void
multVlv( char chr ) // OPEN MULTIPLE VALVES
{
short tool;
if( (chr >= '1' ) && (chr <= '8' ))
{ // SET NEW TOOL
Mode = MANUAL;
tool = (chr & 0X0F); // STRIP OFF 0X3n
posCur( 1, 0 ); // CLEARS ROW 1
Serial.print( (String)"+ "+ToolNam[tool] );
opnVlv( tool );
dcOn();
}
else
cancel( 0 );
}
/*F******************************************************************
* POSITION CURSOR Esc[r;ccf SET CURSOR TO ROW COL
**********************************************************************/
void
posCur( byte row, byte col )
{
char str[8];
strcpy( str, CurPos );
sprintf( &str[2], "%1d;%02df", row, col );
Serial.print( str );
delayMicroseconds( 200 );
}
/*F******************************************************************
* CLEAR SCREEN
**********************************************************************/
void
clrScrn()
{
Serial.print( ClrScrn );
delay( 200 );
DstOnScrn = false;
}
/*F******************************************************************
* RUN A MACHINE
**********************************************************************/
void
dspDust( int dustSpc )
{
char buf[32];
if( !DstOnScrn )
{ // NEED TO REPRINT "Dust Space"
posCur( 3, 0 ); // SET CURSOR POSTION
Serial.print( (String)"Dust Space: ");
DstOnScrn = true;
}
posCur( 3, 12 );
sprintf( buf, "%02u\"", dustSpc );
Serial.print( (String)buf );
}
/*F******************************************************************
* SEND PLANER VALVE (V8) OPEN/CLOSE REQUEST
RETURN: 1 = OK, else -1
**********************************************************************/
short
reqV8( char req ) // REQ IS UC LETTER 'O' or 'C'
{
ulong end;
char chr, resp =0;
short rtn = 1;
V8.listen();
V8.println((String)req ); // SEND PLANER VALVE REQUEST
end = millis() + V8WAT; // SET TIMER FOR PLANER VALVE RESONSE
while( millis() < end )
{ // LOOP HERE WHILE PLANER VALVE MOVES
if( V8.available() )
{ // KEEP READING TIL FIND NEWLINE
chr = V8.read(); // GET RESPONSE: 'O' =OK, 'F' =FAIL
if( chr == NL )
return( rtn ); // END OF RESPONSE
if( (chr != 'O') && (chr != 'K') )
rtn = -1;
}
}
return( -1 ); // TIMEOUT OR FAILED REQ
}
/*F******************************************************************
*
**********************************************************************/
short
v8Fail()
{
posCur( 2, 0 );
Serial.println((String)"V 8 Failed");
cancel( 0 );
return( -1 );
}