rotary table programming

Home Model Engine Machinist Forum

Help Support Home Model Engine Machinist Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

DÉDÉ

Member
Joined
Nov 9, 2022
Messages
6
Reaction score
0
Location
QC CANADA
Hello.From QC Canada I am starting in this field. I am trying to operate my rotary table with a stepper motor. On MEMF, I found a program, I managed to correct an error line 12 for keypad.h it writes: exit status 1 missing terminating "character. I'm stuck and lost, I really need help . If anyone wants to answer me, I will give them all the details
thank you
 
Why don't you tell us a little more about the program and the problem you are having with it. How is it programmed? Is the program secret or can you share it here?
 
Hello.From QC Canada I am starting in this field. I am trying to operate my rotary table with a stepper motor. On MEMF, I found a program, I managed to correct an error line 12 for keypad.h it writes: exit status 1 missing terminating "character. I'm stuck and lost, I really need help . If anyone wants to answer me, I will give them all the details
thank you
The "error: missing terminating '"' character" in C programming language occurs when there is a missing closing double-quote in a string literal.
To fix this error, make sure all string literals in the program have a closing double-quote.
 
Why don't you tell us a little more about the program and the problem you are having with it. How is it programmed? Is the program secret or can you share it here?
Hello no the program is not secret. On the forum as I'm a beginner I didn't want to load too much. If I had an answer I would give him all the details. I found this program from 2009 it includes 240 lines
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte/*
ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display

//setup vars
const int stp = 12; //connect pin 12 to step
const int dir = 13; // connect pin 13 to dir
const int StepsPerRotation = 400; //Set Steps per rotation of stepper
const int TableRatio = 72; //ratio of rotary table
const int Multiplier = (StepsPerRotation * TableRatio)/360;
const int stepdelay = 1;
float Degrees = 0; //Degrees from Serial input
float ToMove = 0; //Steps to move
float Divisions;
float current = 0;
int Mode = 0;


void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.
lcd.backlight();
lcd.print("Rotarye Control");
lcd.setCursor(0,2);
lcd.print(" CrankyTechGuy CNC");
lcd.setCursor(0,3);
lcd.print(" Copyright 2014");
delay(2000);
lcd.init();
Mode = GetMode();
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}

void rotation(float tm, int d)
{
if(d == 0)
{
digitalWrite(dir, LOW);
}
else
{
digitalWrite(dir, HIGH);
}

for(int i = 0; i < tm; i++)
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

float GetNumber()
{
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
char key = kpd.getKey();
lcd.setCursor(0,0);lcd.print("Enterees then");lcd.setCursor(0,3);lcd.print(" press [#].");
lcd.setCursor(0,30);lcd.print("Reset);
lcd.setCursor(8,2);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;

case 'D':
software_Reset();
break;
}

decnum = num / pow(10, counter);
key = kpd.getKey();
}
return decnum;
}

float GetDivisions()
{
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,0);lcd.print("Entersions then");lcd.setCursor(0,1);lcd.print(" press [#].");
lcd.setCursor(0,30);lcd.print("Reset);
lcd.setCursor(8,2);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
software_Reset();
break;
}
key = kpd.getKey();
// num = 360/num;
}
return num;
}

int GetMode()
{
int mode = 0;
lcd.setCursor(0,1);lcd.print("Selectode");

lcd.setCursor(0,3);
lcd.print(" DIV[A] DEG");
while(mode == 0)
{
char key = kpd.getKey();
if(key == 'A')
{
mode = 1;
}
else if(key == 'B')
{
mode = 2;
}
}

lcd.clear();
return mode;
}

void loop()
{
if(Mode == 1)
{
Divisions = GetDivisions();
Degrees = (360/Divisions);
}
if(Mode == 2)
{
Degrees = GetNumber();
}
lcd.clear();
lcd.setCursor(0,3);
lcd.print("FWDEV CAN[C]");
char key = kpd.getKey();
while(key != 'C')
{
lcd.setCursor(0,0);lcd.print("POS:");lcd.print(current);lcd.setCursor(0,1);lcd.print("DPM:");lcd.print(DegreesetKey();
if(key == 'A')
{
if(current >= 360)
{
current = (current + Degrees)-360;
} else {
current = current + Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,2);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
if(key == 'B')
{
if(current <= 0)
{
current = 360+(current - Degrees);
} else {
current = current - Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,0);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
}
lcd.clear();
}





Compilation error: Keypad.h: No such file or directory L1 col 7
best regard André
 
Hello no the program is not secret. On the forum as I'm a beginner I didn't want to load too much. If I had an answer I would give him all the details. I found this program from 2009 it includes 240 lines
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte/*
ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display

//setup vars
const int stp = 12; //connect pin 12 to step
const int dir = 13; // connect pin 13 to dir
const int StepsPerRotation = 400; //Set Steps per rotation of stepper
const int TableRatio = 72; //ratio of rotary table
const int Multiplier = (StepsPerRotation * TableRatio)/360;
const int stepdelay = 1;
float Degrees = 0; //Degrees from Serial input
float ToMove = 0; //Steps to move
float Divisions;
float current = 0;
int Mode = 0;


void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.
lcd.backlight();
lcd.print("Rotarye Control");
lcd.setCursor(0,2);
lcd.print(" CrankyTechGuy CNC");
lcd.setCursor(0,3);
lcd.print(" Copyright 2014");
delay(2000);
lcd.init();
Mode = GetMode();
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}

void rotation(float tm, int d)
{
if(d == 0)
{
digitalWrite(dir, LOW);
}
else
{
digitalWrite(dir, HIGH);
}

for(int i = 0; i < tm; i++)
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

float GetNumber()
{
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
char key = kpd.getKey();
lcd.setCursor(0,0);lcd.print("Enterees then");lcd.setCursor(0,3);lcd.print(" press [#].");
lcd.setCursor(0,30);lcd.print("Reset);
lcd.setCursor(8,2);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;

case 'D':
software_Reset();
break;
}

decnum = num / pow(10, counter);
key = kpd.getKey();
}
return decnum;
}

float GetDivisions()
{
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,0);lcd.print("Entersions then");lcd.setCursor(0,1);lcd.print(" press [#].");
lcd.setCursor(0,30);lcd.print("Reset);
lcd.setCursor(8,2);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
software_Reset();
break;
}
key = kpd.getKey();
// num = 360/num;
}
return num;
}

int GetMode()
{
int mode = 0;
lcd.setCursor(0,1);lcd.print("Selectode");

lcd.setCursor(0,3);
lcd.print(" DIV[A] DEG");
while(mode == 0)
{
char key = kpd.getKey();
if(key == 'A')
{
mode = 1;
}
else if(key == 'B')
{
mode = 2;
}
}

lcd.clear();
return mode;
}

void loop()
{
if(Mode == 1)
{
Divisions = GetDivisions();
Degrees = (360/Divisions);
}
if(Mode == 2)
{
Degrees = GetNumber();
}
lcd.clear();
lcd.setCursor(0,3);
lcd.print("FWDEV CAN[C]");
char key = kpd.getKey();
while(key != 'C')
{
lcd.setCursor(0,0);lcd.print("POS:");lcd.print(current);lcd.setCursor(0,1);lcd.print("DPM:");lcd.print(DegreesetKey();
if(key == 'A')
{
if(current >= 360)
{
current = (current + Degrees)-360;
} else {
current = current + Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,2);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
if(key == 'B')
{
if(current <= 0)
{
current = 360+(current - Degrees);
} else {
current = current - Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,0);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
}
lcd.clear();
}





Compilation error: Keypad.h: No such file or directory L1 col 7
best regard André
Where did you copy this code from, can you supply web address? There is numerous errors in this code.
Line 1 remove */
Line 7 remove /*
Line 88 missing " at the end of Reset should be ("Reset");
Line 138 missing " at the end of Reset should be ("Reset");
Line 204 ?
That is just for starters maybe someone else will can step in with some more help?
 
Last edited:
Hello no the program is not secret. On the forum as I'm a beginner I didn't want to load too much. If I had an answer I would give him all the details. I found this program from 2009 it includes 240 lines
*/
<snip>



Compilation error: Keypad.h: No such file or directory L1 col 7
best regard André

I copied your code into my Arduino IDE, I compiled for Uno hardware. I fixed your missing quotes. Also a mis-spelled attempt to print degrees as degreesetKey.



#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte /* */
ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display

//setup vars
const int stp = 12; //connect pin 12 to step
const int dir = 13; // connect pin 13 to dir
const int StepsPerRotation = 400; //Set Steps per rotation of stepper
const int TableRatio = 72; //ratio of rotary table
const int Multiplier = (StepsPerRotation * TableRatio)/360;
const int stepdelay = 1;
float Degrees = 0; //Degrees from Serial input
float ToMove = 0; //Steps to move
float Divisions;
float current = 0;
int Mode = 0;


void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.
lcd.backlight();
lcd.print("Rotarye Control");
lcd.setCursor(0,2);
lcd.print(" CrankyTechGuy CNC");
lcd.setCursor(0,3);
lcd.print(" Copyright 2014");
delay(2000);
lcd.init();
Mode = GetMode();
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}

void rotation(float tm, int d)
{
if(d == 0)
{
digitalWrite(dir, LOW);
}
else
{
digitalWrite(dir, HIGH);
}

for(int i = 0; i < tm; i++)
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

float GetNumber()
{
float num = 0.00;
//float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
char key = kpd.getKey();
lcd.setCursor(0,0);lcd.print("Enterees then");lcd.setCursor(0,3);lcd.print(" press [#].");
lcd.setCursor(0,30);
lcd.print("Reset");
lcd.setCursor(8,2);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;

case 'D':
software_Reset();
break;
}

decnum = num / pow(10, counter);
key = kpd.getKey();
}
return decnum;
}

float GetDivisions()
{
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,0);lcd.print("Entersions then");lcd.setCursor(0,1);lcd.print(" press [#].");
lcd.setCursor(0,30);lcd.print("Reset");
lcd.setCursor(8,2);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
software_Reset();
break;
}
key = kpd.getKey();
// num = 360/num;
}
return num;
}

int GetMode()
{
int mode = 0;
lcd.setCursor(0,1);lcd.print("Selectode");

lcd.setCursor(0,3);
lcd.print(" DIV[A] DEG");
while(mode == 0)
{
char key = kpd.getKey();
if(key == 'A')
{
mode = 1;
}
else if(key == 'B')
{
mode = 2;
}
}

lcd.clear();
return mode;
}

void loop()
{
if(Mode == 1)
{
Divisions = GetDivisions();
Degrees = (360/Divisions);
}
if(Mode == 2)
{
Degrees = GetNumber();
}
lcd.clear();
lcd.setCursor(0,3);
lcd.print("FWDEV CAN[C]");
char key = kpd.getKey();
while(key != 'C')
{
lcd.setCursor(0,0);lcd.print("POS:");lcd.print(current);lcd.setCursor(0,1);lcd.print("DPM:");lcd.print(Degrees); /*lcd.print(DegreesetKey())*/
if(key == 'A')
{
if(current >= 360)
{
current = (current + Degrees)-360;
} else {
current = current + Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,2);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
if(key == 'B')
{
if(current <= 0)
{
current = 360+(current - Degrees);
} else {
current = current - Degrees;
}
ToMove = Degrees*Multiplier;
lcd.setCursor(0,2);
lcd.print(" Moving ");
rotation(ToMove,0);
lcd.setCursor(0,2);lcd.print(" ");
lcd.setCursor(4,0);lcd.print(" ");
}
}
lcd.clear();
}


This will compile. But I don't know if it will work as I may have the wrong libraries for LiquidCrystal and KeyBoard.
 
You might want to have a look around here too https://www.homemodelenginemachinist.com/threads/help-with-arduino-idexer.35108/, because the code that is posted above has the rounding error described in the other thread!
:) the version i am now using is not "cleaned up" and reversing the direction might be a bad idea, because to use stepper drivers with higher step count, some variables were changed form long to unsigned long.
 
Last edited:
Hi, DÉDÉ I use this you only need to change the level of the turntable (For example: 1:90, 1:72, 1:36 Etc.)

/*
4x4 matrix keypad amd a 20 x 4 LCD. From Bruce.

https://www.homemodelenginemachinis...y-table-for-dummies.26744/page-24#post-376666

A4988 Stepstick/Pololu driver
5/2/2015
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 4 line display
// SCL - A5, SDA - A4, VCC - +5, Gnd - Gnd
//setup vars
const int stp = 2; // connect pin D2 to step
const int dir = 3; // connect pin D3 to dir
const int StepsPerRotation = 400; // Steps per rotation of stepper NOTE the driver is set to Half step
const int TableRatio = 90; // 36 ratio of rotary table
// ***************************************************************************************************
const float Multiplier = 60.0000; //(StepsPerRotation * TableRatio)/360; // 400*90=36000/360 = 100

/*Use the following Multipliers for the indicated ratios
100 to 1 = 111.1111
90 to 1 = 100
72 to 1 = 80.00
60 to 1 = 66.6667
40 to 1 = 44.4444
36 to 1 = 40.0000
32 to 1 = 35.55556
8 to 1 = 8.8889
4 to 1 = 4.4444

*/
// ***************************************************************************************************
const int stepdelay = 1;
float Degrees = 0; // Degrees from Serial input
float ToMove = 0; // Steps to move
float bob = 0;
int cho = 0;

void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.

lcd.backlight();
lcd.print("Rotary Table Control");
lcd.setCursor(4,2);
lcd.print(" ");
lcd.setCursor(3,3);
lcd.print("90-1 Sep 2021");
delay(2000);
lcd.init();
cho = 0;
char key = kpd.getKey();
lcd.print("Enter Selection:");
lcd.setCursor(0,1);
lcd.print("Degrees = A");
lcd.setCursor(0,2);
lcd.print("Divisions = B");
lcd.setCursor(0,3);
lcd.print("JOG = C");
while(cho == 0)
{
key = kpd.getKey();
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees=getdegrees();
lcd.clear();
cho = 1;
break;
case 'B':
Degrees=getdivisions();
cho=2;
break;
case 'C':
Degrees=getjog();
lcd.clear();
cho=3;
break;
} // end case
} // end while cho=0
} // end setup

void loop() // MAIN LOOP
{
lcd.clear();
char key = kpd.getKey();
bob = 0;
lcd.setCursor(7,0);lcd.print("Total: ");lcd.print(bob,2); // total steps
lcd.setCursor(0,3);lcd.print("FOR=A REV=B X=C");
while(key != 'C') // C will return to start menu
{
lcd.setCursor(0,0);lcd.print(abs(Degrees),2);lcd.print((char)223);
key = kpd.getKey();
if(key == 'A') // FORWARD
{
bob = bob + Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, LOW);
printadvance();
}
if(key=='B') // REVERSE
{
bob = bob - Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, HIGH); // pin 13
printadvance();
}
} // end while not C loop
lcd.init();
setup();
} // end main VOID

float getjog()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(6,0);lcd.print("Jogging");
lcd.setCursor(0,1);lcd.print("A=1 B=10 C=100 Steps");
lcd.setCursor(0,2);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees = 1;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'B':
Degrees = 10;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'C':
Degrees = 100;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'D':
num=0.00;
lcd.setCursor(14,2);lcd.print(" ");
lcd.setCursor(14,2);
break;
}
key = kpd.getKey();
}
return Degrees;
}

float getdivisions()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,1);lcd.print("Enter Division:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(16,1);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(16,1);lcd.print(" ");
lcd.setCursor(16,1);
break;
}
Degrees = 360/num;
key = kpd.getKey();
}
return Degrees; //num;
}

float getdegrees()
{
//int key = 0;
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
lcd.clear();
//lcd.init();
char key = kpd.getKey();
lcd.setCursor(0,1);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(15,1);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(15,1);lcd.print(" ");
lcd.setCursor(15,1);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;
} //end case
decnum = num / pow(10, counter);
key = kpd.getKey();
} //end while not #
return decnum;
} // end getdegrees

void printadvance() // print function
{
lcd.setCursor(6,1);lcd.print("Moving");
lcd.setCursor(4,2);lcd.print("Steps ");lcd.print(ToMove,0);
lcd.setCursor(13,0);lcd.print(bob,2);
rotation(ToMove,0);
lcd.setCursor(6,1);lcd.print(" ");
}

void rotation(long tm, int d)
{
for(long i = 0; i < tm; i++) // Problem Fix
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
 
Hi, DÉDÉ I use this you only need to change the level of the turntable (For example: 1:90, 1:72, 1:36 Etc.)

/*
4x4 matrix keypad amd a 20 x 4 LCD. From Bruce.

https://www.homemodelenginemachinis...y-table-for-dummies.26744/page-24#post-376666

A4988 Stepstick/Pololu driver
5/2/2015
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 4 line display
// SCL - A5, SDA - A4, VCC - +5, Gnd - Gnd
//setup vars
const int stp = 2; // connect pin D2 to step
const int dir = 3; // connect pin D3 to dir
const int StepsPerRotation = 400; // Steps per rotation of stepper NOTE the driver is set to Half step
const int TableRatio = 90; // 36 ratio of rotary table
// ***************************************************************************************************
const float Multiplier = 60.0000; //(StepsPerRotation * TableRatio)/360; // 400*90=36000/360 = 100

/*Use the following Multipliers for the indicated ratios
100 to 1 = 111.1111
90 to 1 = 100
72 to 1 = 80.00
60 to 1 = 66.6667
40 to 1 = 44.4444
36 to 1 = 40.0000
32 to 1 = 35.55556
8 to 1 = 8.8889
4 to 1 = 4.4444

*/
// ***************************************************************************************************
const int stepdelay = 1;
float Degrees = 0; // Degrees from Serial input
float ToMove = 0; // Steps to move
float bob = 0;
int cho = 0;

void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.

lcd.backlight();
lcd.print("Rotary Table Control");
lcd.setCursor(4,2);
lcd.print(" ");
lcd.setCursor(3,3);
lcd.print("90-1 Sep 2021");
delay(2000);
lcd.init();
cho = 0;
char key = kpd.getKey();
lcd.print("Enter Selection:");
lcd.setCursor(0,1);
lcd.print("Degrees = A");
lcd.setCursor(0,2);
lcd.print("Divisions = B");
lcd.setCursor(0,3);
lcd.print("JOG = C");
while(cho == 0)
{
key = kpd.getKey();
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees=getdegrees();
lcd.clear();
cho = 1;
break;
case 'B':
Degrees=getdivisions();
cho=2;
break;
case 'C':
Degrees=getjog();
lcd.clear();
cho=3;
break;
} // end case
} // end while cho=0
} // end setup

void loop() // MAIN LOOP
{
lcd.clear();
char key = kpd.getKey();
bob = 0;
lcd.setCursor(7,0);lcd.print("Total: ");lcd.print(bob,2); // total steps
lcd.setCursor(0,3);lcd.print("FOR=A REV=B X=C");
while(key != 'C') // C will return to start menu
{
lcd.setCursor(0,0);lcd.print(abs(Degrees),2);lcd.print((char)223);
key = kpd.getKey();
if(key == 'A') // FORWARD
{
bob = bob + Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, LOW);
printadvance();
}
if(key=='B') // REVERSE
{
bob = bob - Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, HIGH); // pin 13
printadvance();
}
} // end while not C loop
lcd.init();
setup();
} // end main VOID

float getjog()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(6,0);lcd.print("Jogging");
lcd.setCursor(0,1);lcd.print("A=1 B=10 C=100 Steps");
lcd.setCursor(0,2);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees = 1;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'B':
Degrees = 10;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'C':
Degrees = 100;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'D':
num=0.00;
lcd.setCursor(14,2);lcd.print(" ");
lcd.setCursor(14,2);
break;
}
key = kpd.getKey();
}
return Degrees;
}

float getdivisions()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,1);lcd.print("Enter Division:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(16,1);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(16,1);lcd.print(" ");
lcd.setCursor(16,1);
break;
}
Degrees = 360/num;
key = kpd.getKey();
}
return Degrees; //num;
}

float getdegrees()
{
//int key = 0;
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
lcd.clear();
//lcd.init();
char key = kpd.getKey();
lcd.setCursor(0,1);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(15,1);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(15,1);lcd.print(" ");
lcd.setCursor(15,1);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;
} //end case
decnum = num / pow(10, counter);
key = kpd.getKey();
} //end while not #
return decnum;
} // end getdegrees

void printadvance() // print function
{
lcd.setCursor(6,1);lcd.print("Moving");
lcd.setCursor(4,2);lcd.print("Steps ");lcd.print(ToMove,0);
lcd.setCursor(13,0);lcd.print(bob,2);
rotation(ToMove,0);
lcd.setCursor(6,1);lcd.print(" ");
}

void rotation(long tm, int d)
{
for(long i = 0; i < tm; i++) // Problem Fix
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
The choice of the table ratio (in my opinion is the least problem), unless you use the controller with different rotary tables.
Plus we have so many stepper drivers that can do much higher microstepping resolutions than half, quarter or 8th steps.

The problem that the system is under certain conditions not going a full circle is still in this code.
ToMove variable is a float. That float value is then tranfered into the "void rotation(long tm, int d)" function as a long tm, meaning all digits after the comma are ignored by the stepper motor.
All provided I do not read the code wrong and mis something:

With a 4:1 ratio per degree you loose 0.4444 steps out of 4.4444.
When the division is 360 it will move 360*4 steps = 1440 steps.
It should move 400 steps per revolution and four motor revolutions for one table revolution 400 * 4 = 1600 steps. 160 missing steps for a cirlce makes 160/4.4444 = 36° give or take.

So the software will be 36° degrees off, when I want to cut e.g. a graduation scale (not a good thing).

Greetings Timo
 
Last edited:
When I wrote my (arduino) code for my dividing head some years ago- and after numerous computer crashes, I now no longer have the source code!-I calculated each step from scratch, as I figured that way I won't accumulate any error. Seems to work, I don't have any measurable accumulated error after a full 360 degrees.
 
Where did you copy this code from, can you supply web address? There is numerous errors in this code.
Line 1 remove */
Line 7 remove /*
Line 88 missing " at the end of Reset should be ("Reset");
Line 138 missing " at the end of Reset should be ("Reset");
Line 204 ?
That is just for starters maybe someone else will can step in with some more help?
 
Hi, DÉDÉ I use this you only need to change the level of the turntable (For example: 1:90, 1:72, 1:36 Etc.)

/*
4x4 matrix keypad amd a 20 x 4 LCD. From Bruce.

https://www.homemodelenginemachinis...y-table-for-dummies.26744/page-24#post-376666

A4988 Stepstick/Pololu driver
5/2/2015
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};

byte rowPINS[ROWS] = {11,10,9,8};
byte colPINS[COLS] = {7,6,5,4};

Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 4 line display
// SCL - A5, SDA - A4, VCC - +5, Gnd - Gnd
//setup vars
const int stp = 2; // connect pin D2 to step
const int dir = 3; // connect pin D3 to dir
const int StepsPerRotation = 400; // Steps per rotation of stepper NOTE the driver is set to Half step
const int TableRatio = 90; // 36 ratio of rotary table
// ***************************************************************************************************
const float Multiplier = 60.0000; //(StepsPerRotation * TableRatio)/360; // 400*90=36000/360 = 100

/*Use the following Multipliers for the indicated ratios
100 to 1 = 111.1111
90 to 1 = 100
72 to 1 = 80.00
60 to 1 = 66.6667
40 to 1 = 44.4444
36 to 1 = 40.0000
32 to 1 = 35.55556
8 to 1 = 8.8889
4 to 1 = 4.4444

*/
// ***************************************************************************************************
const int stepdelay = 1;
float Degrees = 0; // Degrees from Serial input
float ToMove = 0; // Steps to move
float bob = 0;
int cho = 0;

void setup()
{
lcd.init(); // initialize the lcd
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);

// Print welcome message to the LCD.

lcd.backlight();
lcd.print("Rotary Table Control");
lcd.setCursor(4,2);
lcd.print(" ");
lcd.setCursor(3,3);
lcd.print("90-1 Sep 2021");
delay(2000);
lcd.init();
cho = 0;
char key = kpd.getKey();
lcd.print("Enter Selection:");
lcd.setCursor(0,1);
lcd.print("Degrees = A");
lcd.setCursor(0,2);
lcd.print("Divisions = B");
lcd.setCursor(0,3);
lcd.print("JOG = C");
while(cho == 0)
{
key = kpd.getKey();
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees=getdegrees();
lcd.clear();
cho = 1;
break;
case 'B':
Degrees=getdivisions();
cho=2;
break;
case 'C':
Degrees=getjog();
lcd.clear();
cho=3;
break;
} // end case
} // end while cho=0
} // end setup

void loop() // MAIN LOOP
{
lcd.clear();
char key = kpd.getKey();
bob = 0;
lcd.setCursor(7,0);lcd.print("Total: ");lcd.print(bob,2); // total steps
lcd.setCursor(0,3);lcd.print("FOR=A REV=B X=C");
while(key != 'C') // C will return to start menu
{
lcd.setCursor(0,0);lcd.print(abs(Degrees),2);lcd.print((char)223);
key = kpd.getKey();
if(key == 'A') // FORWARD
{
bob = bob + Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, LOW);
printadvance();
}
if(key=='B') // REVERSE
{
bob = bob - Degrees;
ToMove = (Degrees*Multiplier);
digitalWrite(dir, HIGH); // pin 13
printadvance();
}
} // end while not C loop
lcd.init();
setup();
} // end main VOID

float getjog()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(6,0);lcd.print("Jogging");
lcd.setCursor(0,1);lcd.print("A=1 B=10 C=100 Steps");
lcd.setCursor(0,2);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees = 1;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'B':
Degrees = 10;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'C':
Degrees = 100;
lcd.setCursor(14,2);lcd.print(Degrees);
break;
case 'D':
num=0.00;
lcd.setCursor(14,2);lcd.print(" ");
lcd.setCursor(14,2);
break;
}
key = kpd.getKey();
}
return Degrees;
}

float getdivisions()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,1);lcd.print("Enter Division:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(16,1);

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(16,1);lcd.print(" ");
lcd.setCursor(16,1);
break;
}
Degrees = 360/num;
key = kpd.getKey();
}
return Degrees; //num;
}

float getdegrees()
{
//int key = 0;
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
lcd.clear();
//lcd.init();
char key = kpd.getKey();
lcd.setCursor(0,1);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(15,1);
bool decOffset = false;

while(key != '#')
{
switch (key)
{
case NO_KEY:
break;

case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;

case 'D':
num=0.00;
lcd.setCursor(15,1);lcd.print(" ");
lcd.setCursor(15,1);
break;

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;
} //end case
decnum = num / pow(10, counter);
key = kpd.getKey();
} //end while not #
return decnum;
} // end getdegrees

void printadvance() // print function
{
lcd.setCursor(6,1);lcd.print("Moving");
lcd.setCursor(4,2);lcd.print("Steps ");lcd.print(ToMove,0);
lcd.setCursor(13,0);lcd.print(bob,2);
rotation(ToMove,0);
lcd.setCursor(6,1);lcd.print(" ");
}

void rotation(long tm, int d)
{
for(long i = 0; i < tm; i++) // Problem Fix
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
 
hello Bruce
when I test the program it tells me
Compilation error: Keypad.h: No such file or directory
best regard André
 
hello Bruce
when I test the program it tells me
Compilation error: Keypad.h: No such file or directory
best regard André
In the Arduino IDE, click on tools and then "manage libraries". When that is finished loading, use the search bar at the top right and search for "Keypad". There will be many that show up then. Scroll down until you get to "Keypad" and install that. It should clear up that error message.
 
DEDE

Send me an email at [email protected] with the rotary table ratio eg 90:1 and I will send you a working program. I have sent this program to well over 150 members over several years with no complaints.

Note, you will have to have the libraries installed.

Bruce W-S
 
When I wrote my (arduino) code for my dividing head some years ago- and after numerous computer crashes, I now no longer have the source code!-I calculated each step from scratch, as I figured that way I won't accumulate any error. Seems to work, I don't have any measurable accumulated error after a full 360 degrees.
The modification I posted in the previous thread keeps track of the error and as soon as one full extra step fits in, it will do one more step. So it is limping its way around. A little too less, little too less, little too much etc. At the end it ends up spot on. Awake gave the necessary instruction, so we could come up with a "sort of fix".
Calculation for each position might result in a small numerical error with the float numbers, depends how programmed. Possibly be very "academic" and difficult to spot. But an error of 4° or 10° on one revolution can ruin a gear and make the software useless.
 

Latest posts

Back
Top