// FEEDER CONTROL PROGRAM // // Program name: feeder3.c // Latest revision date: December 8, 1997 // Test results: works just fine // // This program controls the monkey feeder. The feeder drops food pellets // upon request (parallel port input). In addition, color LEDs can be turned // on/off. The feeder is equiped with an infrared sensor which can detect // whether monkey hand is in/out (proximity detector). Moreover, the feeder can // eat its own food either upon request or when the monkey sticks in the hand, // but this is not allowed. // // Programmer: // Mikhail Lebedev // 301-496-4991 // lebedev@lnp.nimh.nih.gov // // Project director: // Andrew Mitz // 301-496-4991 // arm@lnp.nimh.nih.gov // // Technical details // Controller name: Z-World controller "Little G" // Parallel port inputs: // DIGIN1 - if this bit is set to 1, monkey is not allowed to grab food // DIGIN2 - 1/0 red LED off/on, respectively // DIGIN3 - 1/0 green LED off/on, respectively // DIGIN4 - 1/0 blue LED off/on, respectively // DIGIN9 - 1-->0 pulse evokes food presentation // DIGIN10 - 1-->0 pulse evokes food dump // DIGIN12 - proximity sensor 1/0 - out/in (internal connection) // High-current outputs (set bit to 1 to activate an output): // HC1 - feeder valve // HC2 - trap door valve (feeder "mouth") // HC4 - red LED // HC5 - green LED // HC6 - blue LED // Parallel port outputs: // OUTB2 - proximity sensor 1 - hand is out, 0 - in // OUTB3 - trap door state 1 - closed, 0 - open // // Brief description of how the program works // To change the feeder attitude set DIGIN1 (0/1 - waiter/monster) // To turn on/off LEDs, set the corresponding bits (DIGIN2 - 4) to 0/1 // To present food, send a 1-->0 pulse to DIGIN9. The feeder valve will stay // active for 1500 ms (FEED_DELAY). // To dump food, send a 1-->0 pulse to DIGIN10. Trap door (feeder mouth) will // open for 900 ms (DUMP_DELAY). Then, the feeder will wait for the monkey // to remove the hand for a minimum 200 ms (HAND_OUT_DELAY). Then, the trap // door will be closed. Additional 400 ms (PROTECTION_DELAY) will be devoted // to making sure that the monkey does not stick the hand back. If the monkey // does stick the hand back, the trap door is immediately open again, and a new // dump will be sequence initiated. // ------------------------- The program itself --------------------------------- //Delay settings (ms) #define DUMP_DELAY 900L #define HAND_OUT_DELAY 200L #define PROTECT_DELAY 400L #define FEED_DELAY 1500L #use DEFAULT.H //Necessary libraries #use VDRIVER.LIB shared unsigned char dump_flag, //dump control (1-dump) protect_flag, //protect control (1-protect) feed_flag, //feed control (1-feed) proximity_flag, //used in hand out check (1-hand out) dump_trace, //keeps track of dump control input feed_trace; //keeps track of feed control input main () { dump_flag = 0; //inactivate control flags protect_flag = 0; feed_flag = 0; VdInit(); //Initialization stuff VIODrvr(); //Refresh inputs and outputs HC1 = 0; //Feeder valve deactivated HC2 = 0; //Trap door valve deactivated HC4 = 0; //Red light off HC5 = 0; //Green light off HC6 = 0; //Blue light off OUTB2 = 1; //Hand is out (proximity bit) OUTB3 = 1; //Trap door is closed ("safe door" bit) dump_trace = 1; //Traces start at one feed_trace = 1; VIODrvr(); //Put in the initial values while(1) { // Update proximity task costate { VIODrvr(); if (DIGIN12) OUTB2=1; else OUTB2=0; //Update proximity information VIODrvr(); proximity_flag = proximity_flag && DIGIN12; //Flag initialized during dump } // Wait for a command task costate{ VIODrvr(); if (((!DIGIN10)&&(dump_trace != DIGIN10)) //Evoke DUMP on 1-->0 pulse || ((!DIGIN12) && DIGIN1)) { //or hand entering the feeder //when this is not allowed dump_trace = DIGIN10; //update the trace dump_flag = 1; //new job: DUMP abort; //abort because DUMP has a high priority } dump_trace = DIGIN10; //update the trace if ((!DIGIN9)&&(feed_trace != DIGIN9)) { //Evoke FEED on 1-->0 pulse feed_flag = 1; //new job: FEED } feed_trace = DIGIN9; //update the trace if (DIGIN2) HC4=0; else HC4=1; //Red LED if (DIGIN3) HC5=0; else HC5=1; //Green LED if (DIGIN4) HC6=0; else HC6=1; //Blue LED VIODrvr(); //refresh inputs and outputs } // DUMP costate { if (!dump_flag) abort; HC2 = 1; //Open trap door VIODrvr(); OUTB3 = 0; //Inform the "safe door" bit that the trap door is open waitfor(DelayMs(DUMP_DELAY)); //Delay proximity_flag = 0; while( !proximity_flag ) { //The hand should stay out for proximity_flag = DIGIN12; //HAND_OUT_DELAY ms waitfor(DelayMs(HAND_OUT_DELAY)); } HC2 = 0; //Close trap door VIODrvr(); dump_flag = 0; protect_flag = 1; //New job: PROTECT waitfor(DelayMs(PROTECT_DELAY)); //Delay protect_flag = 0; if (!dump_flag) //During PROTECT dump_flag may be set OUTB3 = 1; //"Safe door" is closed } // PROTECT (protect monkey finger from being caught) costate { if (!protect_flag) abort; if (!DIGIN12) { //If the hand is in HC2 = 1; //Open trap door VIODrvr(); dump_flag = 1; //Force a new DUMP } } // FEED costate { if (!feed_flag) abort; HC1 = 1; //Activate feeder valve VIODrvr(); waitfor(DelayMs(FEED_DELAY)); //Stir delay HC1 = 0; //Deactivate feeder valve VIODrvr(); feed_flag = 0; //FEED is finished } } }