I am looking to see if I can change the attached sketch which controls 8 stepper motors to just switching 8 relays for a weaving loom which we have, unfortunately making this change is well above my paygrade lol. I am using an arduino mega and 8 channel relay board which will in turn trip the solenoids which the loom already has attached, thanks for any help
This is the Sketch im trying to alter
// Loom interface for Ashford Dobby interface (using 8 stepper motors):
// Arduino lines 0 & 1 to USB interface
// line 13 Is foot pedal
// 14-43 are motor controls
// General definitions:
#define MAX_CHARS 80
#define DEBUG 0
#define MOTORS 8
#define IDENTITY "Generic Dobby Interface (Jones Stepper Motor Dobby)\n"
// Data controlling motor positions, states, etc:
const long MOTOR_DELAY=900; // Time delay between motor steps (reduce till shafts move reliably)
const long SHAFT_UP=8*170, SHAFT_DOWN=0 ; // Number of motor steps required to raise the shafts
unsigned long shaft_state=0x00000000, shaft_cue=0xffffffff; // tracking current & next desired states of shaft controls
long MotorActual[MOTORS], MotorWant[MOTORS]; // Current & desired position for each of the motors
// Definition of which Output pins connect to which motor
char MotorPin[MOTORS][4]= // Motors 1,3,5,7 on right, 2,4,6,8 on left: left side reverses direcion
{ {14,15,16,17}, {18,21,20,19}, {22,23,24,25}, {26,29,28,27}, // Motors 1-4
{30,31,32,33}, {34,37,36,35}, {38,39,40,41}, {42,45,44,43}}; // Motors 5-8
unsigned long NextMotorUpdate=0; // Timer for when next motor step occurs
const int ADVANCE =13; // input pin for footswitch (has pullup, switch contact only)
// Serial (USB) interface
// Serial interface is a "Generic" dobby interface:
// Host sends which shafts should be activated for current shot
// Shafts will raise when the foot switch is activated
// Shafts return when foot switch is released, and the "Advance" command returned to host
// Also responds to "?" with the "IDENTITY" identified above, shows host who's out here
int serial_chars=0; // Number of characters in the serial input buffer
char serial_string[MAX_CHARS]=""; // Serial input buffer
char Message[MAX_CHARS]=""; // Output message 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 = 1; // set when some host is identified
int Button_state=1; // tracks changes in floor-switch state
////////////////////////////////////////////////////////////////////////
// Send shaft controls to hardware
////////////////////////////////////////////////////////////////////////
void set_motor(char m,char state) // Lowest level function to handle step in motors
{
// sprintf(Message,"M %d @ state %d\n",m,state);
// Serial.write(Message);
switch(state)
{
case 0: // Set motor inactive
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 0);
break;
case 1: // Set motor State 1
digitalWrite(MotorPin[m][0], 1); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 0);
break;
case 2: // Set motor state 2
digitalWrite(MotorPin[m][0], 1); digitalWrite(MotorPin[m][1], 1);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 0);
break;
case 3: // Set motor state 3
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 1);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 0);
break;
case 4: // Set motor state 4
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 1);
digitalWrite(MotorPin[m][2], 1); digitalWrite(MotorPin[m][3], 0);
break;
case 5: // Set motor state 5
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 1); digitalWrite(MotorPin[m][3], 0);
break;
case 6: // Set motor state 6
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 1); digitalWrite(MotorPin[m][3], 1);
break;
case 7: // Set motor state 7
digitalWrite(MotorPin[m][0], 0); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 1);
break;
case 8: // Set motor state 8
digitalWrite(MotorPin[m][0], 1); digitalWrite(MotorPin[m][1], 0);
digitalWrite(MotorPin[m][2], 0); digitalWrite(MotorPin[m][3], 1);
break;
}
}
char set_motors() // Set all motors to new motor state - called for each motor step on any motor
{ // return indicates if any motor is still active
int m=0;
long setting, entry_setting;
char active=0;
while(m<MOTORS)
{
// Check for necessary directional movement
entry_setting=setting=MotorActual[m];
if(setting==MotorWant[m]) setting=setting;
else if(setting<MotorWant[m]) setting++;
else setting--;
// Send update setting controls
if((entry_setting!=MotorWant[m]))
{
active=1;
MotorActual[m]=setting; // update actual for move in progress
setting=(setting&7)+1; // set_motor state 0 is inactive, 1-8 are active
set_motor(m,setting); // Set new motor state
}
m++; // Next motor
}
if(active==0)
{ // If done kill power to the motors that are back in passive state
m=0;
while(m<MOTORS)
{
if(MotorActual[m]==SHAFT_DOWN)set_motor(m,0); // set motor inactive
m++;
}
}
return active;
}
char run_motors() // Higher level function to set motors to desired positions
{ // return indicates if motors are active or idle
char active=1;
if(micros()>=NextMotorUpdate)
{ // time to update the motor positions
active=set_motors(); // Update all motors
NextMotorUpdate=micros()+MOTOR_DELAY; // set clock for next update
}
return active;
}
void set_shafts(unsigned long shafts) // Called to set desired motor positions based on which shafts were requested
{ // This assumes all shafts move the same amount, they really don't need to
unsigned long bit_mask=1;
int i=0;
while(i<MOTORS)
{
if(shafts&bit_mask)MotorWant[i]=SHAFT_UP;
else MotorWant[i]=SHAFT_DOWN;
// sprintf(Message,"M %d @ want %d\n",i,MotorWant[i]>>8);
// Serial.write(Message);
i++;
bit_mask=bit_mask<<1;
}
}
////////////////////////////////////////////////////////////////////////
// Preset- Called on initialization
////////////////////////////////////////////////////////////////////////
void preset() // Could raise all shafts to show it's working, etc.
{ // This version doesn't do anything, default will lift all shafts when the foot switch is pressed before anything else is requested
}
//////////////////////////////////////////////////
// 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) // Input is series of numbers, comma seperated, for shafts to raise
{ // returns word indicating which shafts were identified in string
int chars=strlen(command); // Number of characters in input string
int i=0;
unsigned long shafts=0, bits; // Sets bits for shafts indicated
char shaft=0, digit=0, character;
while(i<=chars) // loop through all characters in command
{
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<<shaft-1;
shafts|=bits;
shaft=0;
}
}
else if(('0'<=character)&&(character<='9'))
{ // have digit
character&=0x0f; // reduce to decimal
shaft=shaft*10+character;
}
else if((character==' ')||(character=='\n')); // ignore spaces/returns
else
{
Serial.println("Invalid Character detected in command:"); // debug display of command extracted
Serial.println(command); // debug display of command extracted
i=chars; // quit, got crap
}
i++;
}
return shafts;
}
void digest_serial(char* command) // Main serial response function
{
int chars=strlen(command); // Number of characters in command
if(chars>0)
{ // If something to do go digest the input
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 binary word
else if((command[0]=='c')||(command[0]=='t')) // test command to cycle valves
preset(); // cycle through the valves (nothing defined for this loom, could implement shaft self test, etc)
else if(command[0]=='?')
{ // Have a "Who are You?" kind of command, tell host who we are
char message[256]=IDENTITY; // Build primary Identity command
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); // Send identity with current switch state to host (for troubleshooting)
}
}
}
void serial_input()
{ // High level Serial processing
char inChar;
char command[MAX_CHARS]="";
while((Serial.available()>0))
{ // Get serial command from host (character by character)
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))))
{ // If have a command, go digest it
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
}
}
////////////////////////////////////////////////////////////// /
// Foot Switch monitor - set shafts/tell host to advance
////////////////////////////////////////////////////////////// /
void monitor_button()
{ // check for button push to advance, sent only when button pushed (not held)
char state=digitalRead(ADVANCE); // read state of foot switch (0=active, 1=inactive)
if(state==0)
{ // button is pressed,
set_shafts(shaft_cue); // Set motor desired states from the list of shafts desired for this shot
run_motors(); // Go run the motors to make it happen
}
else
{ // button is not pressed,
set_shafts(0); // Set motor desired states back to reset condition
run_motors(); // Make it happen
if(Button_state!=state)
Serial.write("ADVANCE\n"); // Send "Advance" when foot switch is released
}
if(state!=Button_state) // Check if button has changed state
delay(500); // Wait half a second on changes to debounce switch
Button_state=state; // Track current state of the button to look for changes
}
//////////////////////////////////////////////////
// TOP LEVEL FUNCTIONS - SETUP & LOOP //
//////////////////////////////////////////////////
void setup()
{
char m; // Motor indicator
// USB Interface to host computer
Serial.begin(9600); // start serial port at 9600 bps:
Serial.print(IDENTITY); // print message on serial monitor
// Motor Controls
// set motor controls for all motors
m=0;
while(m<MOTORS)
{
digitalWrite(MotorPin[m][0], LOW); // set low
digitalWrite(MotorPin[m][1], LOW); // set low
digitalWrite(MotorPin[m][2], LOW); // set low
digitalWrite(MotorPin[m][3], LOW); // set low
pinMode(MotorPin[m][0], OUTPUT); // Set as output bit
pinMode(MotorPin[m][2], OUTPUT); // Jumble order to keep motor from moving
pinMode(MotorPin[m][1], OUTPUT); // Set as output bit
pinMode(MotorPin[m][3], OUTPUT); // Set as output bit
MotorWant[m]=MotorActual[m]=0; //
m++;
}
pinMode(ADVANCE, INPUT_PULLUP); // Set as input pin to handle the foot switch
preset(); // "self test" - note it's alive
unsigned long T0=millis(); // Note start up time
}
void loop()
{
serial_input(); // check the serial interface, handle if it comes in
monitor_button(); // check for button push
}