//Loom interface for Macomber Dobby interface replacement: // Arduino lines 0 & 1 to USB interface // lines 2-13 are output controls for shafts // analog input 0 used for floor button #define IDENTITY "Generic Dobby Interface (Jones Air Dobby)\n" // Arudino Uno is adequate for this since it just needs 14 digital lines for 12 shafts plus 2 Serial I/O to host // Gets commands from the USB , use ULN2003a drivers (2) to control 12V pneumatic valves to move shafts on loom // Uses analog input for the foot switch to leave digital lines for controls #define MAX_CHARS 80 #define DEBUG 0 // Serial (USB) interface int serial_chars=0; // Number of characters in the serial input buffer char serial_string[MAX_CHARS]=""; // Serial input buffer long serial_time=0; // Used to close serial string on timeout (timer) const int serial_timeout=100; // Digest Serial string after timeout char serial_idle=1; // Tracks activity on the serial bus char HostPresent = 0; // set when some host is identified const int BUTTON_UP=0; const int BUTTON_DOWN=1; int Button_state=BUTTON_UP; const int ADV_THRESHOLD=128; long Button_T0=0; // time for last state change unsigned long shaft_state=0x00000000, shaft_cue=0x00000000; // tracking current & next desired states of shaft controls const int SHAFT01 = 2; // Control bit for shaft const int SHAFT02 = 3; // Control bit for shaft const int SHAFT03 = 4; // Control bit for shaft const int SHAFT04 = 5; // Control bit for shaft const int SHAFT05 = 6; // Control bit for shaft const int SHAFT06 = 7; // Control bit for shaft const int SHAFT07 = 8; // Control bit for shaft const int SHAFT08 = 9; // Control bit for shaft const int SHAFT09 =10; // Control bit for shaft const int SHAFT10 =11; // Control bit for shaft const int SHAFT11 =12; // Control bit for shaft const int SHAFT12 =13; // Control bit for shaft const int ADVANCE =00; // analog input channel for Advance button push ////////////////////////////////////////////////////////////////////////// // Send shaft controls to hardware ///////////////////////////////////////////////////////////////////////// void set_shafts(unsigned long shafts, int Tdelay) { // set controls to state defined by input word shaft_state=shafts; // backup to global if(shafts&0x800) digitalWrite(SHAFT12, HIGH); //Control bit is high else digitalWrite(SHAFT12, LOW); //Control bit is low delay(Tdelay); if(shafts&0x400) digitalWrite(SHAFT11, HIGH); //Control bit is high else digitalWrite(SHAFT11, LOW); //Control bit is low delay(Tdelay); if(shafts&0x200) digitalWrite(SHAFT10, HIGH); //Control bit is high else digitalWrite(SHAFT10, LOW); //Control bit is low delay(Tdelay); if(shafts&0x100) digitalWrite(SHAFT09, HIGH); //Control bit is high else digitalWrite(SHAFT09, LOW); //Control bit is low delay(Tdelay); if(shafts&0x080) digitalWrite(SHAFT08, HIGH); //Control bit is high else digitalWrite(SHAFT08, LOW); //Control bit is low delay(Tdelay); if(shafts&0x040) digitalWrite(SHAFT07, HIGH); //Control bit is high else digitalWrite(SHAFT07, LOW); //Control bit is low delay(Tdelay); if(shafts&0x020) digitalWrite(SHAFT06, HIGH); //Control bit is high else digitalWrite(SHAFT06, LOW); //Control bit is low delay(Tdelay); if(shafts&0x010) digitalWrite(SHAFT05, HIGH); //Control bit is high else digitalWrite(SHAFT05, LOW); //Control bit is low delay(Tdelay); if(shafts&0x008) digitalWrite(SHAFT04, HIGH); //Control bit is high else digitalWrite(SHAFT04, LOW); //Control bit is low delay(Tdelay); if(shafts&0x004) digitalWrite(SHAFT03, HIGH); //Control bit is high else digitalWrite(SHAFT03, LOW); //Control bit is low delay(Tdelay); if(shafts&0x002) digitalWrite(SHAFT02, HIGH); //Control bit is high else digitalWrite(SHAFT02, LOW); //Control bit is low delay(Tdelay); if(shafts&0x001) digitalWrite(SHAFT01, HIGH); //Control bit is high else digitalWrite(SHAFT01, LOW); //Control bit is low } ////////////////////////////////////////////////////////////////////////// // Preset- cycle all shaft controls sequentially ///////////////////////////////////////////////////////////////////////// void preset() { int Td=200; // delay between setting shafts - 2.4 sec first to last set_shafts(0x0fff, Td); // ramp all shafts up set_shafts(0x0000, Td); // then back down } ////////////////////////////////////////////////// // SERIAL INTERFACE (USB) FUNCTIONS // ////////////////////////////////////////////////// // USB input commands: // 1,2,3,n Set shafts 1,2,3,n // ? ID request, respond with ID unsigned long get_shafts(char* command) { int chars=strlen(command); int i=0; unsigned long shafts=0, bits; char shaft=0, digit=0, character; char message[1000]; while(i<=chars) { character=command[i]; if((character==',')||(i==chars)) { // have field seperator or end of string, not shaft desired if((shaft>0)&&(shaft<=32)) { // 'shafts' notes this shaft is required bits=1<0) { HostPresent=1; // note that there's something out there talking to me if(('0'<=command[0])&&(command[0]<='9')) // go number, should be shafts shaft_cue=get_shafts(command); // convert ASCII string to hex string else if((command[0]=='c')||(command[0]=='t')) // test command to cycle valves preset(); // cycle through the valves else if(command[0]=='?') { char message[256]=IDENTITY; message[strlen(message)-1]=0; // delete return in line sprintf(message,"%s [Solenoid state = 0x%3x]\n",message,shaft_state); // note what we'll do when button is pressed Serial.write(message); } } } void serial_input() { char inChar; char command[MAX_CHARS]=""; while((Serial.available()>0)) { inChar=char(Serial.read()); serial_string[serial_chars]=inChar; serial_chars++; serial_string[serial_chars]=0; serial_time=millis(); } if((serial_chars>0)&&(serial_idle)&&((serial_string[serial_chars-1]=='\n')||(millis()>(serial_time+serial_timeout)))) { serial_idle=0; strcpy(command,serial_string); serial_chars=0; serial_string[0]=0; //Serial.println(command); // debug display of command extracted digest_serial(command); // done with last command, clear the input buffers serial_idle=1; // ready for more serial input } } /////////////////////////////////////////////////////////////// // Floor button handler - set shafts/tell host to advance // /////////////////////////////////////////////////////////////// void monitor_button() { // check for button push to advance, sent only when button pushed (not held) int level=analogRead(ADVANCE); char state=0; long ButtonDelay=2000; // button debouncer long now=millis(), then=Button_T0+ButtonDelay; int td=25; //mSec delay time in setting/resetting shafts // check current state if(level=then)) { Button_T0=now; Button_state=state; if(HostPresent==0) { if(Button_state==BUTTON_DOWN) { Serial.write("Button down, no host\n"); preset(); // cycle through the valves } } else { if(Button_state==BUTTON_DOWN) { // button pressed, send command set_shafts(shaft_cue,td); } else { Serial.write("ADVANCE\n"); set_shafts(0, td); } } } } ////////////////////////////////////////////////// // TOP LEVEL FUNCTIONS - SETUP & LOOP // ////////////////////////////////////////////////// void setup() { // USB Interface to host computer Serial.begin(9600); // start serial port at 9600 bps: Serial.print(IDENTITY); //print message on serial monitor // shaft solenoid controls digitalWrite(SHAFT06, LOW); digitalWrite(SHAFT01, LOW); digitalWrite(SHAFT02, LOW); digitalWrite(SHAFT03, LOW); digitalWrite(SHAFT04, LOW); digitalWrite(SHAFT05, LOW); digitalWrite(SHAFT07, LOW); digitalWrite(SHAFT08, LOW); digitalWrite(SHAFT09, LOW); digitalWrite(SHAFT10, LOW); digitalWrite(SHAFT11, LOW); digitalWrite(SHAFT12, LOW); pinMode(SHAFT01, OUTPUT); //Shaft controls pinMode(SHAFT02, OUTPUT); //Shaft controls pinMode(SHAFT03, OUTPUT); //Shaft controls pinMode(SHAFT04, OUTPUT); //Shaft controls pinMode(SHAFT05, OUTPUT); //Shaft controls pinMode(SHAFT06, OUTPUT); //Shaft controls pinMode(SHAFT07, OUTPUT); //Shaft controls pinMode(SHAFT08, OUTPUT); //Shaft controls pinMode(SHAFT09, OUTPUT); //Shaft controls pinMode(SHAFT10, OUTPUT); //Shaft controls pinMode(SHAFT11, OUTPUT); //Shaft controls pinMode(SHAFT12, OUTPUT); //Shaft controls preset(); // "self test" - note it's alive } void loop() { serial_input(); // check the serial interface, handle if it comes in monitor_button(); // check for button push }