//Loom interface for HobbyDobby interface
// for Table Loom 4 Shafts
#define IDENTITY "Generic Dobby Interface (HobbyDobby)\n"
#define MAX_CHARS 80
// 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;
unsigned long shaft_state=0x00000000, shaft_cue=0x00000000, oldshafts=0x00000000; // tracking current & next desired states of shaft controls
const int ADVANCE =00; // analog input channel for Advance button push
// Кнопки
#define BTN_PIN01 10 // sw1 Hand/Auto кнопка подключена сюда (BTN_PIN --- КНОПКА --- +5)
#define BTN_PIN02 11 // sw2 PROG/COMP
#define BTN_PIN03 12 // sw3 CURRENT ON/OFF
#define BTN_PIN04 13 // sw4 NEXT ON/OFF
#define BTN_PIN05 15 // sw5 SHAFT01
#define BTN_PIN06 16 // sw6 SHAFT02
#define BTN_PIN07 17 // sw7 SHAFT03
#define BTN_PIN08 18 // sw8 SHAFT04
#include "GyverButton.h"
GButton butt_sw1(BTN_PIN01);
GButton butt_sw2(BTN_PIN02);
GButton butt_sw3(BTN_PIN03);
GButton butt_sw4(BTN_PIN04);
GButton butt_sw5(BTN_PIN05);
GButton butt_sw6(BTN_PIN06);
GButton butt_sw7(BTN_PIN07);
GButton butt_sw8(BTN_PIN08);
#include <GyverStepper2.h>
GStepper2<STEPPER2WIRE> stepper1(200, 2 , 3); // драйвер step-dir
GStepper2<STEPPER2WIRE> stepper2(200, 4 , 5); // драйвер step-dir
GStepper2<STEPPER2WIRE> stepper3(200, 6 , 7); // драйвер step-dir
GStepper2<STEPPER2WIRE> stepper4(200, 8 , 9); // драйвер step-dir
int MaxSpeed=4000; // 10000 work - 400 debug
int Acceleration=7000;
int MaxPos=50; // 5000 work - 50 debug
int MaxPosDebug=50;
int iPolCurentPosition=0; // счетчик полотняного переплетения
//////////////////////////////////////////////////////////////////////////
// Send shaft controls to hardware
/////////////////////////////////////////////////////////////////////////
void set_shafts(unsigned long shafts)
{ // set controls to state defined by input word
shaft_state=shafts; // backup to global
if (shafts==0)
{
stepper1.setTarget(0);
stepper2.setTarget(0);
stepper3.setTarget(0);
stepper4.setTarget(0);
}
else
{
if(shafts&0x008) stepper4.setTarget(MaxPos);//Control bit is high
else stepper4.setTarget(0); //Control bit is low
if(shafts&0x004) stepper3.setTarget(MaxPos);//Control bit is high
else stepper3.setTarget(0); //Control bit is low
if(shafts&0x002) stepper2.setTarget(MaxPos);//Control bit is high
else stepper2.setTarget(0); //Control bit is low
if(shafts&0x001) stepper1.setTarget(MaxPos);//Control bit is high
else stepper1.setTarget(0); //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); // ramp all shafts up
//set_shafts(0x0000); // 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<<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)
{
int chars=strlen(command);
if(chars>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;
butt_sw4.tick();
butt_sw3.tick();
// check current state
if(butt_sw4.state()) state=BUTTON_DOWN;
else state=BUTTON_UP;
if(HostPresent==0)
{
if(butt_sw4.isPress())
{
Serial.write("Button down, no host\n");
preset(); // cycle through the valves
}
}
else
{
if(butt_sw4.isPress())
{ // button pressed, send command
set_shafts(shaft_cue);
}
if (butt_sw4.isRelease())
{
oldshafts=shaft_cue;
Serial.write("ADVANCE\n");
set_shafts(0);
}
if (butt_sw3.isPress()) set_shafts(oldshafts);
if (butt_sw3.isRelease()) set_shafts(0);
}
}
///////////////////////////////////////////////////////////////
// простое полотно 1,3 - 2,4
///////////////////////////////////////////////////////////////
void prog_polotno()
{
if(butt_sw4.isPress())
{ // button pressed, send command
// Serial.println(iPolCurentPosition); // debug display of command extracted
if (iPolCurentPosition==0) set_shafts(0x001+0x004);
else set_shafts(0x002+0x008);
}
if (butt_sw4.isRelease())
{
if (iPolCurentPosition==0) iPolCurentPosition=1;
else iPolCurentPosition=0;
set_shafts(0);
}
if (butt_sw3.isPress())
{ if (iPolCurentPosition>0) set_shafts(0x001+0x004);
else set_shafts(0x002+0x008);
}
if (butt_sw3.isRelease()) set_shafts(0);
}
///////////////////////////////////////////////////////////////
// pickUp 2,3 - 1,4
///////////////////////////////////////////////////////////////
void prog_pickup()
{
if(butt_sw4.isPress())
{ // button pressed, send command
// Serial.println(iPolCurentPosition); // debug display of command extracted
if (iPolCurentPosition==0) set_shafts(0x002+0x004);
else set_shafts(0x001+0x008);
}
if (butt_sw4.isRelease())
{
if (iPolCurentPosition==0) iPolCurentPosition=1;
else iPolCurentPosition=0;
set_shafts(0);
}
if (butt_sw3.isPress())
{ if (iPolCurentPosition>0) set_shafts(0x002+0x004);
else set_shafts(0x001+0x008);
}
if (butt_sw3.isRelease()) set_shafts(0);
}
///////////////////////////////////////////////////////////////
// саржа 1-2-3-4
///////////////////////////////////////////////////////////////
void prog_sarga1234()
{
if(butt_sw4.isPress())
{ // button pressed, send command
// Serial.println(iPolCurentPosition); // debug display of command extracted
if (iPolCurentPosition==0) set_shafts(0x001);
else if (iPolCurentPosition==1) set_shafts(0x002);
else if (iPolCurentPosition==2) set_shafts(0x004);
else set_shafts(0x008);
}
if (butt_sw4.isRelease())
{
iPolCurentPosition = iPolCurentPosition + 1;
if (iPolCurentPosition == 4) iPolCurentPosition = 0;
set_shafts(0);
}
if (butt_sw3.isPress())
{
if (iPolCurentPosition==0) set_shafts(0x008);
else if (iPolCurentPosition==1) set_shafts(0x001);
else if (iPolCurentPosition==2) set_shafts(0x002);
else set_shafts(0x004);
}
if (butt_sw3.isRelease()) set_shafts(0);
}
///////////////////////////////////////////////////////////////
// саржа 12-23-34-41
///////////////////////////////////////////////////////////////
void prog_sarga12233441()
{
if(butt_sw4.isPress())
{ // button pressed, send command
// Serial.println(iPolCurentPosition); // debug display of command extracted
if (iPolCurentPosition==0) set_shafts(0x001+0x002);
else if (iPolCurentPosition==1) set_shafts(0x002+0x004);
else if (iPolCurentPosition==2) set_shafts(0x004+0x008);
else set_shafts(0x008+0x001);
}
if (butt_sw4.isRelease())
{
iPolCurentPosition = iPolCurentPosition + 1;
if (iPolCurentPosition == 4) iPolCurentPosition = 0;
set_shafts(0);
}
if (butt_sw3.isPress())
{
if (iPolCurentPosition==0) set_shafts(0x008+0x001);
else if (iPolCurentPosition==1) set_shafts(0x001+0x002);
else if (iPolCurentPosition==2) set_shafts(0x002+0x004);
else set_shafts(0x004+0x008);
}
if (butt_sw3.isRelease()) set_shafts(0);
}
///////////////////////////////////////////////////////////////
// саржа 1-3-2-4 рваная
///////////////////////////////////////////////////////////////
void prog_sarga1324()
{
if(butt_sw4.isPress())
{ // button pressed, send command
// Serial.println(iPolCurentPosition); // debug display of command extracted
if (iPolCurentPosition==0) set_shafts(0x001);
else if (iPolCurentPosition==1) set_shafts(0x004);
else if (iPolCurentPosition==2) set_shafts(0x002);
else set_shafts(0x008);
}
if (butt_sw4.isRelease())
{
iPolCurentPosition = iPolCurentPosition + 1;
if (iPolCurentPosition == 4) iPolCurentPosition = 0;
set_shafts(0);
}
if (butt_sw3.isPress())
{
if (iPolCurentPosition==0) set_shafts(0x008);
else if (iPolCurentPosition==1) set_shafts(0x001);
else if (iPolCurentPosition==2) set_shafts(0x004);
else set_shafts(0x002);
}
if (butt_sw3.isRelease()) set_shafts(0);
}
///////////////////////////////////////////////////////////////
// Управление программным режимом
// кнопки sw5-sw6 программные режимы
///////////////////////////////////////////////////////////////
void monitor_button_prog()
{ // программа - полотняное переплетение
butt_sw3.tick();
butt_sw4.tick();
butt_sw5.tick();
butt_sw6.tick();
butt_sw7.tick();
butt_sw8.tick();
if (butt_sw5.state() == 0 && butt_sw6.state() == 0 && butt_sw7.state() == 0 && butt_sw8.state() == 0) prog_polotno();
if (butt_sw5.state() == 1 && butt_sw6.state() == 0 && butt_sw7.state() == 0 && butt_sw8.state() == 0) prog_pickup();
if (butt_sw5.state() == 0 && butt_sw6.state() == 1 && butt_sw7.state() == 0 && butt_sw8.state() == 0) prog_sarga1234();
if (butt_sw5.state() == 0 && butt_sw6.state() == 0 && butt_sw7.state() == 1 && butt_sw8.state() == 0) prog_sarga12233441();
if (butt_sw5.state() == 0 && butt_sw6.state() == 0 && butt_sw7.state() == 0 && butt_sw8.state() == 1) prog_sarga1324();
}
//////////////////////////////////////////////////
// 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
// регулятор скорости
pinMode(A5, INPUT);
// устанавливаем опрос кнопок на автоматический
butt_sw1.setTickMode(AUTO);
butt_sw2.setTickMode(AUTO);
butt_sw3.setTickMode(AUTO);
butt_sw4.setTickMode(AUTO);
butt_sw5.setTickMode(AUTO);
butt_sw6.setTickMode(AUTO);
butt_sw7.setTickMode(AUTO);
butt_sw8.setTickMode(AUTO);
butt_sw1.setType(HIGH_PULL);
butt_sw2.setType(HIGH_PULL);
butt_sw3.setType(HIGH_PULL);
butt_sw4.setType(HIGH_PULL);
butt_sw5.setType(HIGH_PULL);
butt_sw6.setType(HIGH_PULL);
butt_sw7.setType(HIGH_PULL);
butt_sw8.setType(HIGH_PULL);
// настройка шаговиков
stepper1.setMaxSpeed(MaxSpeed);
stepper1.setAcceleration(Acceleration);
stepper1.setTarget(0);
stepper2.setMaxSpeed(MaxSpeed);
stepper2.setAcceleration(Acceleration);
stepper2.setTarget(0);
stepper3.setMaxSpeed(MaxSpeed);
stepper3.setAcceleration(Acceleration);
stepper3.setTarget(0);
stepper4.setMaxSpeed(MaxSpeed);
stepper4.setAcceleration(Acceleration);
stepper4.setTarget(0);
}
void loop() {
MaxPos = map(analogRead(A5),0,1023, 10, MaxPosDebug);
stepper1.tick();
stepper2.tick();
stepper3.tick();
stepper4.tick();
if (!butt_sw1.state()) { // Кнопка HAND не нажата
if (butt_sw5.isPress()) stepper1.setTarget(MaxPos);
if (butt_sw5.isRelease()) stepper1.setTarget(0);
if (butt_sw6.isPress()) stepper2.setTarget(MaxPos);
if (butt_sw6.isRelease()) stepper2.setTarget(0);
if (butt_sw7.isPress()) stepper3.setTarget(MaxPos);
if (butt_sw7.isRelease()) stepper3.setTarget(0);
if (butt_sw8.isPress()) stepper4.setTarget(MaxPos);
if (butt_sw8.isRelease()) stepper4.setTarget(0);
}
else { // Кнопка HAND нажата
if (butt_sw2.state()) { // Кнопка COMP нажата
serial_input(); // check the serial interface, handle if it comes in
monitor_button(); // check for button push
}
else { // Кнопка COMP не нажата
monitor_button_prog();
}
}
}