# Tips for Arduno software for Rotary Table Controllers



## rodw (Feb 8, 2015)

EDIT: Latest Sketch (V9) is on post #155: http://www.homemodelenginemachinist.com/showpost.php?p=262782&postcount=155
This is a substantial upgrade that supports ramping stepper speeds up and down and also saves defaults in the EEPROM so you don't have to recompile it if you change your hardware.
You will need to copy the header file into your Arduino libaries so it is included It is a standard Arduino library from here http://playground.arduino.cc/Code/EEPROMWriteAnything

The last  version before this upgrade is:
post #108: http://www.homemodelenginemachinist.com/showpost.php?p=262304&postcount=108

The first version with REQUIRED libraries and links are on Post #20:
http://www.homemodelenginemachinist.com/showpost.php?p=262061&postcount=39
---------------------------------------------------------------------------------------------------------------
As promised I thought I'd share some stuff I've learnt about in relation to Arduino programming with particular reference to Rotary Table controllers You see, Chuck Fellowes inspired me ages ago but being still in the workforce, I jut have never had the time to get this project off the ground despite putting in some really solid stints on programming before running out of time and found to was to hard to pick up where I left off each time.  Now that TorontoBuilder working on his project and there is some interest, I thought I'd share what I've learnt as it might inspire some one to pick up where I left off.

*Manage your memory*
So the first thing to know with the Arduino is quite tiny in relation to its dynamic memory that is used to store variables. You MUST store string data (eg text data) in Program memory or you will run out of room, the stack will overflow and things get unpredictable. Ask me how I know?

Do it like this:

```
const char item_Eggs[] PROGMEM = "Eggs";
```
If you don't do this, the Arduino will store it in program memory, and copy the data into dynamic memory at runtime. Just remember that PROGMEM cannot be altered.

As your program grows in size, pay careful attention to the Arduino output.

```
Sketch uses 13,532 bytes (41%) of program storage space. Maximum is 32,256 bytes.
Global variables use 470 bytes (22%) of dynamic memory, leaving 1,578 bytes for local variables. Maximum is 2,048 bytes.
```

*Pick your numbers*
The next thing to consider is the size of numbers that you need to deal with. Using floating point arithmetic is costly in terms of both memory usage and execution time. In  dividing head dealing with discrete 360 degrees per revolution and steppers with a finite number of steps per revolution, there is no need to use floating point maths. an integer is not large enough if somebody (like me) uses a microstepping drive (like the Geckos which have 2000 steps per rev). Go with a long data type (4 byte value). There is also no reason no deal with negative values as we have a direction pin on the stepper controller to tell us which direction to rotate.  So why not work with unsigned longs which can handle up to 4,294,967,295 that should be enough!

Just be aware, that if you take a big number away from a smaller number, unsigned numbers cannot show a negative number, so validate your data carefully!

Also, when you stop and think about measuring an angle, the base units we use are degrees, minutes and seconds. If you internally work in seconds, there is no need to use floating point maths at all. There are only 1296000 seconds in a circle!

*Use the timer Interrupt to drive our stepper*
Typically, most stepper code I see uses delay() for stepper pulses. This is a bad idea as it can halt the arduino from doing its own internal housekeeping during the delay. There is a much better way to achieve the same thing and that is to attach to the timer interrupt. Interrupts let you pass off processing to the CPU outside of your main program logic, hence their name. So we simply tell the CPU a time period to fire and  it will magically run a procedure for you while you are doing other stuff. The key here is to keep your interrupt service routine (ISR) a short as possible. There is an included ISR example sketch for the Arduino that flashes the LED on the board which you can modify easily to drive a stepper controller. Here is a working (but trivial example) configured for the Gecko microstepper. Divide the values (4000 and 8000) by 10 if you are using a Polou driver.


```
#include <TimerOne.h>
#define stepPin 4
#define dirPin 5
#define CLOCKWISE     HIGH
#define ANTICLOCKWISE LOW
int dir = CLOCKWISE;  // Clockwise
int state = LOW;
int steps = 8000;
int ctr = 0;

void setup() 
{
  // Initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards
  pinMode(13, OUTPUT);    
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  digitalWrite(dirPin, HIGH);
  digitalWrite(stepPin, state);
  
  Timer1.initialize(40); // set a timer of length in microseconds (or 0.1 sec - or 10Hz
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}
 
void loop()
{
  // Main code loop
  // TODO: Put your regular (non-ISR) logic here
int i;
    if(!steps && ctr < 10){  
      delay(200);
      dir = dir ^ 1;
      digitalWrite(dirPin, dir);
      if(dir == CLOCKWISE)
          steps = 8000;  
      else
          steps = 4000;
      ctr++;
    }

}
 
/// --------------------------
/// Custom ISR Timer Routine
/// --------------------------
void timerIsr()
{
    // Toggle LED
  if(steps){
      digitalWrite( 13, digitalRead( 13 ) ^ 1 );
      state = state ^ 1;
      digitalWrite( stepPin, state );
      steps--;
  }
}
```

Yeh, I know I said never to use delay() but this is just a simple test sketch (It will also blink the LED.

*Store configuration in EEPROM*
I hate hard coding configuration data. The Arduino has an EEPROM which can be thought of a a tiny hard drive. The UNO has 1024 bytes of read/write EEPROM. Why not store your global data in there? This is pretty easy if you create  global structure that contains all of your config data and include a signature in the first few characters. That way, you can look in the EEPROM and decide if there is data to retrieve or it is empty.

This link explains how.  
http://playground.arduino.cc/Code/EEPROMLoadAndSaveSettings

I've found this to be really easy to enable.

*Use a Data Entry Library that lets you build a form for data entry.*
Arduinos are not often required to tell you whats happening on a built in display, much less let you key data in. I've had a lot of trouble finding a good data entry library. I started to write my own and had it pretty complete  but was plagued by keyboard bounce issues on my Freetronics keyboard/display board. Then I found a good one for the Freetronics board. It was still not perfect as it was missing two data types; Angles (in degrees, minutes and seconds) and a routine that allowed you to enter arbitrary numbers without thousands of keyboard presses!

Something like this:

```
DegreeField degreeField(mainForm, "Rotation", 360, DEGREEFIELD_READ_WRITE);
```
and this:

```
GetIntField stepField(mainForm, "Number of steps", 9999, GETINTFIELD_READ_WRITE);
```

the beauty of this library is that you can build forms containing several fields that are treated as one complete unit. This substantially reduces coding overheads. Here is my demo form containing all supported data types


```
Form mainForm(lcd);
TextField welcomeField(mainForm, "Form example", "v1.0");
TimeField timeField(mainForm, "Time since reset", 24, TIMEFIELD_READ_ONLY);
DegreeField degreeField(mainForm, "Rotation", 360, DEGREEFIELD_READ_WRITE);
IntField volumeField(mainForm, "Volume", 0, 100, 5, 85, "%");
BoolField ledField(mainForm, "Status LED", "On", "Off", true);
ListField ingredient(mainForm, "  <Main Menu>  ", ingredients);
GetIntField stepField(mainForm, "Number of steps", 9999, GETINTFIELD_READ_WRITE);
```

*Order by the menu*
Life becomes really easy if you can use a menu system that allows you to define the complete interface before coding anything If you set up a Todo procedure, you can then progressively replace each to do procedure with live code. Something like this:


```
void setupMenus()
{  
  g_menuLCD.MenuLCDSetup();  
MENU_ACTION_CALLBACK_FUNC func);
   p_menuEntryRoot = new MenuEntry(menuEntries[0], NULL, NULL);

  g_menuManager.addMenuRoot( p_menuEntryRoot );
    g_menuManager.addChild( new MenuEntry(menuEntries[1], NULL, HomeSetCallback) );
  g_menuManager.addChild( new MenuEntry(menuEntries[2], NULL, HomeGotoCallback ) );
  g_menuManager.addChild( new MenuEntry(menuEntries[3], (void *) &g_menuManager, MenuEntry_BackCallbackFunc) );

  g_menuManager.addSibling( new MenuEntry(menuEntries[4], NULL, NULL ) );
..................
..................
..................
..................
  g_menuManager.addSibling( new MenuEntry( menuEntries[32], NULL, CreditsCallback) );
  //Make sure the menu is drawn correctly after all changes are done
  about();
  g_menuManager.DrawMenu();
}
```


```
// Define Device Backlash Parameters eg. Mechanical number of steps required to take up backlash
void EditDevBackLashCallback( char* pMenuText, void *pUserData )
{	
	ToDo();
	g_isDisplaying = true;  
}
```
And a simple stub for each menu procedure

```
void ToDo( void)
{
    g_menuLCD.ClearLCD();
    g_menuLCD.getLCD()->setCursor( 0,0 );
    g_menuLCD.getLCD()->print("To Do");
    g_menuLCD.getLCD()->setCursor( 0,1 );
    flashscreen();
}
```
Phew, Thats probably enough for one post. More to come!


----------



## Swifty (Feb 8, 2015)

Is there a laymans version of this, it may as well be written in Latin as far as I'm concerned, I'm completely bamboozled 

I wish that I could do this type of thing, I'm keen to make an electronic dividing head.

Paul.


----------



## Wizard69 (Feb 8, 2015)

rodw said:


> So why not work with unsigned longs which can handle up to 4,294,967,295 that should be enough!



Famous last words!    I'd run the numbers to make sure you can do at least ten revolutions of the table.   Obviously that depends upon gear ratios and micro stepping settings.  I think we need a spread sheet here.


----------



## rodw (Feb 8, 2015)

Swifty said:


> Is there a layman a version of this, it may as well be written in Latin as far as I'm concerned, I'm completely bamboozled
> 
> I wish that I could do this type of thing, I'm keen to make an electronic dividing head.
> 
> Paul.



Paul, Bit like TorontoBuilder's hardware project for me. 

Hopefully some members will pick up and run with this so it becomes a working project as there seem to be some pretty clever guys on board. The arduino is really simple to program to do simple things, but it is the software that makes it rock! And it does not even come with a keyboard, we have to build our own!

I'll post up some of the code soon.


----------



## Wizard69 (Feb 8, 2015)

Swifty said:


> Is there a layman a version of this, it may as well be written in Latin as far as I'm concerned, I'm completely bamboozled


Arduinos are programmed in a variant of C/C++.   I say variant because they don't use all of the standard libraries.   This means you need Arduino specific references.  


> I wish that I could do this type of thing, I'm keen to make an electronic dividing head.
> 
> Paul.



Unfortunately Arduinos result in hacked up hardware.   If this rotary table PCB works out it will simplify things a bit.


----------



## Swifty (Feb 8, 2015)

I bought a book on basic arduino last year, I suppose I better read it.

Paul.


----------



## Cogsy (Feb 8, 2015)

Swifty said:


> I bought a book on basic arduino last year, I suppose I better read it.
> 
> Paul.


 
You can buy a cheap arduino clone starter kit off ebay for around $30 and they usually come with starter projects. The starter guides are handy and you will learn the fundamentals of coding as you build them.

 If you spend around $60 your kit will include many more sensors as well as small servos and steppers to play around with. Not reallly suited to real-world applications but you will learn a heap playing with them. (unless the real world application is building an autonomous robot that is)

A couple of examples : starter kit, more advanced kit

I bought a kit about mid-range of these two a while back and learned more about programing in C++ than I did when I studied it at Uni!


----------



## rodw (Feb 8, 2015)

For the Aussies, you can also grab a Freetronics starter kit from any Jaycar store as like Cogsy has described. Its pretty cool when you get a computer interfacing with the outside world

Well, I've had some encouraging (but not great) results. I merged my form handling code and Rotary table menu code together and it compiled first go! 

So I embedded a form in one of the menu procedures and it opened when I navigated to it but immediately hung. I think I have a conflict between the LCD handling code between the two libraries as they both create different LCD instances using different classes.


----------



## Scott_M (Feb 8, 2015)

Thanks Rod !
Following along closely. My coding skills are very weak. The more I mess with it the clearer it becomes. It really makes a difference when you are trying to do something that you "want" to do. It just somehow seems to make more sense.
I am still having a lot of issues with syntax, I can "read" most code and tell what it is doing, but still run into trouble writing it.

Scott


----------



## canadianhorsepower (Feb 8, 2015)

This is probably the best place in the world to get
any kind of stuff. Check the price of arduino

and free shipping
http://www.dx.com/s/arduino?categoryId=473

cheers


----------



## TorontoBuilder (Feb 8, 2015)

I'll be following closely and working on learning coding for the arduino myself...


----------



## rodw (Feb 8, 2015)

Scott_M said:


> Thanks Rod !
> Following along closely. My coding skills are very weak. The more I mess with it the clearer it becomes. It really makes a difference when you are trying to do something that you "want" to do. It just somehow seems to make more sense.
> I am still having a lot of issues with syntax, I can "read" most code and tell what it is doing, but still run into trouble writing it.
> 
> Scott



You are welcome Scott. Syntax will come with practice. Make sure you take the time to format your code neatly as it helps to debug. Any book on C coding will help. Just remember the Arduimo hides the main () procedure which is the first C procedure that runs on startup. It will still be there  internally and look like this:

```
main ()
{
   setup();
   while (1)
      loop();
}
```

People say the Arduino code is different to C. It isn't,  just some standard functions have been left out due to size. Other things just are not documented.


----------



## /// (Feb 8, 2015)

canadianhorsepower said:


> This is probably the best place in the world to get
> any kind of stuff. Check the price of arduino
> 
> and free shipping
> ...


Caveat Emptor


----------



## RonGinger (Feb 8, 2015)

Rod, is there a data entry or menu library you are using, or is this something you are writing? Is it, or will it be available? It sounds like a very useful library.


----------



## kiwi2 (Feb 9, 2015)

I'm with Swifty on this.
A couple of years ago I bought an Arduino kit and did all the exercises that came with it. Very interesting. When I came to actually make something, ( a readout for a load cell) I found my electronics knowledge wasn't up to it so the kit has been sitting in a drawer ever since.
When Chuck came up with his electronic dividing head, I started following the various threads and had more or less decided to have a crack at one this winter.
After reading Rods' post however, I don't think I'll bother. It seems to be mind bogglingly difficult to do what I would have thought would be a fairly simple procedure i.e. to send a set number of pulses to a stepper motor.
I guess I'll wait until electronic dividing heads are available or someone comes out with a kit.

Alan C.


----------



## rodw (Feb 9, 2015)

kiwi2 said:


> I'm with Swifty on this.
> A couple of years ago I bought an Arduino kit and did all the exercises that came with it. Very interesting. When I came to actually make something, ( a readout for a load cell) I found my electronics knowledge wasn't up to it so the kit has been sitting in a drawer ever since.
> When Chuck came up with his electronic dividing head, I started following the various threads and had more or less decided to have a crack at one this winter.
> After reading Rods' post however, I don't think I'll bother. It seems to be mind bogglingly difficult to do what I would have thought would be a fairly simple procedure i.e. to send a set number of pulses to a stepper motor.
> ...



Alan, yes it is sImple. Use Chucks code for now or buy Kwackers kit based on a PIC controller. I'm trying to take it to the next level but constrained by time.


----------



## canadianhorsepower (Feb 9, 2015)

/// said:


> Caveat Emptor


 
I don't have any Idea why you put this remark

Ive been buying stuff from there for many years and all
my students do also with out any problem.
About $300.00 a month and never disapointed.

Of course some of the 1.00 deal are  1.00 item
I just got 10  module l 298 h driver for the price of one
in Canada do I care if one burns Rof}Rof}
But they don't come with instruction SO WHAT


----------



## /// (Feb 9, 2015)

It's only a warning, nothing more.
Where there's smoke, there's fire.
If you've had nothing but joy, great.
I got burned, never got what I ordered and never saw my money again. A quick google search is all anyone needs to do to see I'm far from alone.


----------



## rodw (Feb 13, 2015)

I'm afraid I have put quite a few hours (days) trying to merge my form library with the menu library With no success. There is no valid reason I can see why its failing so I suspect a stack over flow. Very frustrating. I need to rethink what my approach will be.


----------



## rodw (Feb 14, 2015)

Well, I've had some problems getting this all together but I do have a working stepper driver sketch for the Freetronics Keyboard
http://www.freetronics.com.au/collections/display/products/lcd-keypad-shield#.VN_HtvmUeSo

You will also need the timer1 library from the Arduino Playground
http://playground.arduino.cc/Code/Timer1

I am also using a modified version of this library to mange the Freetronics Keyboard and mange menus and input forms
https://github.com/rweather/arduinolibs

I've added two new field types to this class:
*DegreeField *- which inputs or displays an angle in degrees, minutes or seconds.  The underlying data type is an unsigned long which is the number of seconds in the included angle.

*GetIntField* - despite its name, this inputs an unsigned long using arbitrary  input. Eg. you can cursor along the field (using left and right buttons) and click on the up/down buttons to increment and decrement a digit below the cursor.

To navigate a form with multiple fields using this library (which we are going to do), just use the left and right arrows.

I'd recommend you play with the form example included in the LCD library to get you head around how this library works.

Note, the sketch includes a screen saver (from the LCD library) so don't panic if the screen goes blank, just press any key!

On startup, press any key to proceed to the next screen to enter the number of divisions (defaults to 3) with up and down buttons. Press right to cursor to the next field. This displays the included angle per division. Press the right arrow again. This gets you to the <Go Divide> function. Press either up or down to get to the divide screen. It will Say 
Div: 1 of 3 and display the included angle
Simply press left or right to move the dividing head one division.
Press Select to exit this routine and return to the main menu.

My thinking was to add a few more functions to the main menu to change speed, turn continuously and manage backlash etc. The other feature that might be useful is to actually slow the stepper down as it gets to the end of it travel in case the inertia pushes the stepper on one step. These menus will occur after <Go Divide> option so they won't get in the way. These will be really easy to add as all of the keyboard handling is in the LCD class.

The freetronics LCD library could probably be modified for other boards with an analog keyboard by altering pin assignments and voltage values for each button. 

Note the Stepper Pins I've used differ from Chuck's so as not to conflict with those used by the Freetronics LCD board. I've attached zip files containing my modified library and the sketch itself. Don't forget to add the Timer1 library. 

This is a much more robust and extensible Rotary Table controller than what the forum has had before.

Let me know how you get on!

PS If anybody designs a stepper motor  adapter for a Vetex 6" Rotary Table, I'd appreciate a copy of the plans. 

View attachment RotaryTableChuck1.zip


View attachment LCD.zip


----------



## Scott_M (Feb 14, 2015)

WOW

Thanks Rod !

I have the SainSmart LCD. I will see if it is adaptable, if not I will get the FreeTronics, I like those buttons better anyway.

Many Thanks

Scott


----------



## rodw (Feb 15, 2015)

Scott_M said:


> WOW
> 
> Thanks Rod !
> 
> ...



Good luck with it Scott. I connected a NEMA 23 stepper up to my 90:1 Vertex 6" rotary table today and with a few tweaks, it works!

Initially, I was missing a few steps so I experimented with changing the Timer delay and slowed it down to get more torque. I also swapped the values around for the Direction.


```
#define CLOCKWISE     LOW
#define ANTICLOCKWISE HIGH
#define TIMER_DELAY 80
```

I took a few photos of how I attached the stepper to the table so will post them up later this evening. First time I broached a keyway and it worked nicely.

I just held the Stepper in my hands at this stage. The next "step" is to make the mount to attach it permanently. I was never sure if the stepper I had was strong enough to drive the table.


----------



## rodw (Feb 15, 2015)

Photo time.

First all of the hardware






The Arduino and Freetronics Terminal Shield with the LCD display on top.  The Gecko GX251 Micro drive stepper driver. It is being powered by a 19 volt laptop power supply. You can see I have used a flexible coupler for the stepper motor.






In business mode!

THis is the Gecko controller






Here is the 6" Rotary table with the handle removed





The shaft is 12mm and the keyway is 4mm. The diameter of the backplate is 56mm. I have some 55mm round stock here that will be perfect to make the mount from. You can see the plate at the back has some M5 threaded holes in it. I made these on a PCD of 32mm.

So I decided if I made a 20mm long collar with a 12mm bore, I could broach a keyway in  it. 

Then all I'd need to do would be to make a 20mm long adapter shaft that was M12 at one end (with a keyway milled in it) and 8mm to match the stepper shaft at the other.

Sorry, but when I checked my stock of keys, I did not have a 4mm one so I had to file one down and I ended up pressing it in (it's tight!) so no photo of the adapter shaft but you'll get the idea.






I did not bother to add a set screw here as once its assembled, it can't fall apart. I have to get M3 set screw though!

And here's the other end that will mate up with the rotary table shaft.






So here is it all in place!






Initially, I made the collar out of 19mm dia aluminium and thought there might not be enough meat for the keyway so I remade it out of 25mm. I should have used the original one! I've since turned the collar down to 20mm to make it easier to gain clearance for the adapter.

I've measured up the adapter and will draw it up properly, but it looks  pretty straightforward. It will need a slot in it to reach the various set screws.


----------



## Scott_M (Feb 15, 2015)

Success !!

It works with the SainSmart LCD shield. I had to change my step and direction wires to 1&2 from 2&3. I also had to change the timer delay, 50 worked but I changed it to 60 for a little more margin of safety. I also added more delay to the screensaver(30) 10 sec was too short, the screen would blank before it finished making some moves requiring 2 button presses to go to the next position. I set div to 1 and timed it, with this power supply 21 sec. for 90 turns of the motor.

You mentioned something about moving the cursor and entering values, was that something that will be implemented or should work now?
If it should work now, either it does not or I can't figure it out.
All the buttons seem to do what they are supposed to , up , down , left , right and select.

This is more than sufficient for my needs , just curious about the cursor.

Very well done sir !! Many thanks !

Scott

EDIT

I just played with the Form sketch, The cursor moves there and I can change values. ???


----------



## Scott_M (Feb 15, 2015)

Video of the mock up, set for a 90 turn table with 10 microsteps. 

www.sdmfabricating.com/upload_page/RodWRoTab.MOD 

Scott


----------



## TorontoBuilder (Feb 15, 2015)

Scott_M said:


> Success !!
> 
> It works with the SainSmart LCD shield. I had to change my step and direction wires to 1&2 from 2&3. I also had to change the timer delay, 50 worked but I changed it to 60 for a little more margin of safety. I also added more delay to the screensaver(30) 10 sec was too short, the screen would blank before it finished making some moves requiring 2 button presses to go to the next position. I set div to 1 and timed it, with this power supply 21 sec. for 90 turns of the motor.
> 
> ...



is the complete working code posted somewhere?


----------



## darkoford (Feb 15, 2015)

Great Rod! Thm:

I have a problem with the keys, how and where to make it right?

Thank you!


----------



## Scott_M (Feb 15, 2015)

TorontoBuilder said:


> is the complete working code posted somewhere?


 
Yes, Post #20


----------



## rodw (Feb 15, 2015)

RonGinger said:


> Rod, is there a data entry or menu library you are using, or is this something you are writing? Is it, or will it be available? It sounds like a very useful library.



Ron, sorry, I missed this. I'd tried writing my own and then found a couple of promising libraries but they refused to play together. I dropped one and bave posted all of the required resources on post #20 
http://www.homemodelenginemachinist.com/showpost.php?p=261783&postcount=20

So read on from there.


----------



## rodw (Feb 15, 2015)

Scott_M said:


> Success !!
> 
> It works with the SainSmart LCD shield. I had to change my step and direction wires to 1&2 from 2&3. I also had to change the timer delay, 50 worked but I changed it to 60 for a little more margin of safety. I also added more delay to the screensaver(30) 10 sec was too short, the screen would blank before it finished making some moves requiring 2 button presses to go to the next position. I set div to 1 and timed it, with this power supply 21 sec. for 90 turns of the motor.
> 
> ...



Scott, awesome that you have got this up and running with so few changes.  I was kinda hoping the keyboards were compatible with each other.

I had thought of disabling the screen saver on entry to the godivide () function and reenabling on exit but your solution is probably better. It did not annoy me until i got out in the shed.

Glad you sorted out the cursor as I didn't have a clue what I had said.


----------



## Scott_M (Feb 15, 2015)

Hi Rod
The cursor works in the form sketch
But not in your sketch, on my setup. Again, I am not really sure I need it, just giving feedback.

Again, many thanks

Scott


----------



## rodw (Feb 15, 2015)

darkoford said:


> Great Rod! Thm:
> 
> I have a problem with the keys, how and where to make it right?
> 
> Thank you!



The Freetronics and SainsSmart are an analog keyboard so they use a single analog port with a series of resistors that alter the voltage to a known value when a key is pressed. Freetronics has a good description of how this works and the wiring diagram for them.

If your keys are not analog keys then it won't work. If they are analog keys, search in the LCD library code for call to an analog read and review the code there. Change it to values that suit you. Or make your own keyboard and use the resistor values Freetronics uses. You can change the analog port when you create the LCD variable.


----------



## darkoford (Feb 15, 2015)

rodw said:


> You can change the analog port when you create the LCD variable.



This is what I use.



At Chuck first version worked like this:

 if (adc_key_in < 60)   return btnRIGHT;  
 if (adc_key_in < 200)  return btnUP; 
 if (adc_key_in < 400)  return btnDOWN; 
 if (adc_key_in < 880)  return btnLEFT; 
 if (adc_key_in < 950)  return btnSELECT;  

My C ++ is bad so now I do not know where I change the value in your program.

Thanks for your help!


----------



## rodw (Feb 15, 2015)

darkoford said:


> This is what I use.
> 
> 
> 
> ...



Assuming you have made your own keyblard as per the circuit shown, and are not using a pre made shield, you could replace your resistors with the values shown here
http://www.freetronics.com.au/pages/16x2-lcd-shield-quickstart-guide#.VOFbeZt47MI

That would provide compatability with the Sainsmart and Freetronics boards which might be a good thing.


----------



## rodw (Feb 15, 2015)

Ok, modifying the code to use different resistor values is not simple.

In LCD.cpp, this code needs to be modified


> // Button mapping table generated by genlookup.c
> static unsigned char const buttonMappings[] PROGMEM = {
> 2, 0, 0, 0, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 1,
> 1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0
> };



It is generated by a separate program (genlookup.c) designed to run on a desktop PC. The program is here and is part of the LCD library I linked to in post #20.
https://github.com/rweather/arduinolibs/blob/master/gen/genlookup.c

So what you have to do is to establish the values returned by each button by an analog read, Then modify genlookupc.c 

and change these values


```
#define LCD_BUTTON_VALUE_GAP    10
#define LCD_BUTTON_RIGHT_VALUE  0
#define LCD_BUTTON_UP_VALUE     145
#define LCD_BUTTON_DOWN_VALUE   329
#define LCD_BUTTON_LEFT_VALUE   505
#define LCD_BUTTON_SELECT_VALUE 741
```

Then compile and run the program and insert the output into LCD.cpp

You could run this generator on an Arduino if you modify genlookup.c to use serial.print to print it to the serial port.


----------



## rodw (Feb 16, 2015)

Just added a new feature for jogging.

Left and right button turn the table either direction while the button is held down.
Up and down button moves left or right 1 single step. 

Initially I though this code was not working with my microstep drive but if you hold you hand on the stepper, you could just feel the slightest bump (angle is 0.8 seconds) so I changed it to 10 steps. eventually, I will make this user configurable.

Give me a few more days to add a bit more to it before I post up the code.

Speed control, home position memory, and enter a dividing angle in DMS still to come.


----------



## Scott_M (Feb 16, 2015)

Very Cool !!

Scott ( your faithful beta tester )


----------



## darkoford (Feb 16, 2015)

rodw said:


> Assuming you have made your own keyblard as per the circuit shown, and are not using a pre made shield, you could replace your resistors with the values shown here
> http://www.freetronics.com.au/pages/16x2-lcd-shield-quickstart-guide#.VOFbeZt47MI
> 
> That would provide compatability with the Sainsmart and Freetronics boards which might be a good thing.



Resistance values are the same on my schedule as well as on http://www.freetronics.com.au/pages/16x2-lcd-shield-quickstart-guide#.VOFbeZt47MI

I think the problem was the length of the wires that were not coax so that the issue is resolved one capacitor.

It would be good to add in parallel to each key by a capacitor cca.100nF.




Thanks for your help!

Btw. It would be good to do (do not know his name) and this possibility


----------



## rodw (Feb 18, 2015)

Hi guys, I've attached an update for my faithful beta testers. The code has been changed quite a lot so beware any bugs!

 We now have the following features:
1. Menu has changed to make it flatter. To open a menu procedure, press the up or down arrows
2. Pressing Select exits a procedure.
3. Divide feature entering # of divisions
4. Divide feature by entering Degrees, Minutes, Seconds. Cursor left and right along the field and change digits with the up and down buttons. Press Select to move to operation 
5. Jog function. Rotary Table operates continuously while the left or right button is held down.  Up and down button moves stepper NUMBER_JOG_STEPS each button press. This should let you get a perfect setup if say you wanted to drill holes in the side of a hex bar.

The other feature I want to add is the ability to remember a home position and be able to return to that position by simply pressing a button. That needs a bit of thought as the distance from home needs to be maintained within the ISR procedure. 

View attachment RotaryTableChuck2.zip


----------



## Scott_M (Feb 18, 2015)

Hi Rod
I may have time later today to give this a try. Sounds like a bunch of new features. I hope the cursor works for me now.
I will report back.

Thanks again

Scott


----------



## chucketn (Feb 18, 2015)

I downloaded your code, Rod, and it will not compile. Many errors. Are you using the libraries that came with the Arduino IDE, or new ones?.
First error is " 'LCD' does not name a type."

Chuck


----------



## Scott_M (Feb 18, 2015)

Hi Chuck

Yes he is, go back to post 20 I think the LCD library link is there. You'll also need the Timer library.

Scott

Edit from post 20 and the LCD as a zip file


Well, I've had some problems getting this all together but I do have a working stepper driver sketch for the Freetronics Keyboard
http://www.freetronics.com.au/collec...d#.VN_HtvmUeSo

You will also need the timer1 library from the Arduino Playground
http://playground.arduino.cc/Code/Timer1 

View attachment LCD.zip


----------



## TorontoBuilder (Feb 18, 2015)

rodw said:


> Hi guys, I've attached an update for my faithful beta testers. The code has been changed quite a lot so beware any bugs!
> 
> We now have the following features:
> 1. Menu has changed to make it flatter. To open a menu procedure, press the up or down arrows
> ...



It works on my arduino, but I dont have a stepper motor to try it with. I LOVE the menu, and the method of entering numbers, its just what I was planning. GREAT JOB

A couple of issues I found...

After program set and running, the display shuts off after 30 seconds. This would happen while cutting a gear tooth and appears to be power saving feature that may have been copied from another sketch?

The user must hit a key to reactivate the display, then hit right button to advance the rotary table. I'd prefer to have the display remain active. I doubt anyone is using battery power so power conservation not an issue.

Issue two, when setting degrees if you mistakenly enter a value in the 100's of degrees column (say 100 00' 00") there is no way to clear the 100's  integer value back to zero, you are stuck with either 1, 2 or 3. The only option is to reset the arduino and start over. This could be fixed to allow zero as a valid input

Question, would it be easy to change the ratio and math to make this work to control a non rotary table indexing head with 5 to 1 ratio with the obvious limitation on step resolution to 0.36 deg per step?


----------



## Scott_M (Feb 18, 2015)

Hi Rod

Very nice work !
I had a few minutes at lunch time to try it, Everything works great. I also agree with TB about the screensaver. But I just increased the wait time to 3 minutes, which I think will be fine for now. A lot will depend on what has to be done when you get to the indexed position.

Thank you so much for all of your hard work, it is appreciated very much !

Scott


----------



## TorontoBuilder (Feb 18, 2015)

I thought I'd try to make a quick change to see how easy this sketch would be to adapt to a more basic indexing head. 

I changed the step resolution to 1000 to reflect 200 full steps per motor x 5 for the 5 to 1 gear ratio. Then I programmed in 6 deg per step... but the math converted to 62 steps when the result should have been 60 teeth...

see image 1

I then tried 1200 steps per revolution and got a good result for that one gear setting at least... 

see image 2

anyway I'll have to play with this more to understand the math and rounding the sketch is doing.


----------



## chucketn (Feb 18, 2015)

The timer library link shows 2 libraries. Which one do I need?
I have the Sainsmart LCD. I will try it with that.

Chuck


----------



## Scott_M (Feb 18, 2015)

Chuck
I used the first one      here is the link   http://code.google.com/p/arduino-timerone/downloads/list

Scott


----------



## TorontoBuilder (Feb 18, 2015)

chucketn said:


> The timer library link shows 2 libraries. Which one do I need?
> I have the Sainsmart LCD. I will try it with that.
> 
> Chuck



The newest one... check the dates. I had no trouble with my sainsmart lcd display and keypad.


----------



## TorontoBuilder (Feb 18, 2015)

Thanks to these threads on the arduino and rotary tables I have finally gotten the motivation to dig out my hemingway rotary table kit. 

Sadly I'm still not up and running on my lathe thanks to the utter incompetence of the busybee tools recommended delivery stooge.


----------



## chucketn (Feb 18, 2015)

I can't get Rod's sketch to work. It loads, I can set divisions, but the stepper doesn't move, and successive steps give a garbled display.
I'm back to using Chuck F's sketch, and will give my poor brain a rest.

Chuck


----------



## Scott_M (Feb 18, 2015)

Hi Chuck

Did you switch the step and direction pins ?
Chucks used  2 & 3
Rods uses 1 & 2

I am pretty sure I just had to move the wire from 3  to 1  ,  2 stayed where it was.


Scott


----------



## darkoford (Feb 18, 2015)

chucketn said:


> I can't get Rod's sketch to work. It loads, I can set divisions, but the stepper doesn't move, and successive steps give a garbled display.



Try :

_#define stepPin *1*
#define dirPin *2*
_
replace:

_#define stepPin *2*
#define DirPin *1*_

Or if you are using some other pins.


----------



## rodw (Feb 18, 2015)

Wow guys, 2 pages of comments while I was sleeping!

I have edited post #1 to point to the posts with the latest code and will maintain that over time As I add new versions.

A couple of things:

All parameters you need # steps, stepper pins etc are all configurable in the #defines and global variables at the top of the sketch. I had to change the pins because of a conflict with the freetronics board.

To change a value from say 100 degrees to 90 degrees, position the cursor in the tens column, not the hundreds, and the down button will let you change the hundreds. This code is in the degreefield files that are part of the LCD library. I wrote this new class based on tbe existing time field datdata type. I did not want the cursor to be left hanging. Maybe I can change how this works.

The maths looks convoluted. It got confusing. Initially, I was simply calculating the number of stepper steps per division. Then when we wanted to enter an arbitrary angle, I changed it so that the stepper steps is calculated from the angle. The angle is maintained internally in seconds so it does not need to muck about with odd data types. Eg 1 degree is internally stored as 3600 seconds. The number of seconds in a circle is WAY more than any conceiveable number of stepper steps in a circle so the conversion maths seems to still be accurate so I settled on this for all divisions. The code that uses float data type basically simply calculates the ratio for the entered angle vs 360*60*60 seconds in a circle then multiplies that by the number of steps in a circle. If I did not use a float, we got rounding errors.

If the Screen saver triggers, the stepper dividing functions won't be affected as the interrupt routine still runs in the background. The keystroke that enables the display and it gets eaten so it does not affect anything. Eg. does not trigger another division! You can comment out the call in the setup () function.

So a question. Should the number of divisions be entered as an arbitrary number like the angles are entered? Currently it starts at 1 and goes up or down 1 step at a time.


----------



## TorontoBuilder (Feb 18, 2015)

chucketn said:


> I can't get Rod's sketch to work. It loads, I can set divisions, but the stepper doesn't move, and successive steps give a garbled display.
> I'm back to using Chuck F's sketch, and will give my poor brain a rest.
> 
> Chuck



Chuck just modify these two entries:
#define stepPin 1
#define dirPin 2

changing to this:

#define stepPin 3   //Digital Pin 3 outputs Step Execution
#define dirPin 2     //Digital Pin 2 outputs Step Direction

assuming your system kept Chuck Fellow's program unmodified.

Always try to change software before hardware...


----------



## TorontoBuilder (Feb 18, 2015)

rodw said:


> So a question. Should the number of divisions be entered as an arbitrary number like the angles are entered? Currently it starts at 1 and goes up or down 1 step at a time.



divisions shud be entered as arbitrary number like angles are entered if possible... entering 60 sucks at present.

Not sure I followed how to comment out the screen saver...

Do I change this code:
 lcd.enableScreenSaver(30);

to this:
 lcd.enableScreenSaver();


----------



## chucketn (Feb 18, 2015)

I changed the step and direction parameters to match my physical setup. I used 4 and 3.

Chuck


----------



## rodw (Feb 18, 2015)

TorontoBuilder said:


> I thought I'd try to make a quick change to see how easy this sketch would be to adapt to a more basic indexing head.
> 
> I changed the step resolution to 1000 to reflect 200 full steps per motor x 5 for the 5 to 1 gear ratio. Then I programmed in 6 deg per step... but the math converted to 62 steps when the result should have been 60 teeth...
> 
> ...



When stepping by degrees, the number of steps (62) is meaningless as it is the number of steps per stepper movement that counts. You'd need to check that the stepper is actually moving 6 degrees. I am pretty sure it will be. I reused the same procedure to save code space, maybe the "of 62" should not be displayed in this case. If you think about it, if you set a movement of 300 degrees, it is not an equal division of a circle.

Hopefully the error you observed has on affect on the code.


----------



## rodw (Feb 18, 2015)

rodw said:


> When stepping by degrees, the number of steps (62) is meaningless as it is the number of steps per stepper movement that counts. You'd need to check that the stepper is actually moving 6 degrees. I am pretty sure it will be. I reused the same procedure to save code space, maybe the "of 62" should not be displayed in this case. If you think about it, if you set a movement of 300 degrees, it is not an equal division of a circle.
> 
> Hopefully the error you observed has on affect on the code.



I think the "of 62 error" error is here
on line 214 in enterDegrees()

```
divisions = STEPS_PER_REV /  stepsPerDiv;
```
this should be linked to degrees for greater acuracy

I have not tried it, but I think it should be like

```
divisions = (long)((float) MINUTES_IN_CIRCLE / (float) angleField.value());
```


----------



## TorontoBuilder (Feb 18, 2015)

rodw said:


> I think the "of 62 error" error is here
> on line 214 in enterDegrees()
> 
> ```
> ...



I am sure that it doesnt help that 6 degrees isnt equally divisible by the 0.36 deg /step if I change div /rotation to 1000


----------



## rodw (Feb 18, 2015)

TorontoBuilder said:


> divisions shud be entered as arbitrary number like angles are entered if possible... entering 60 sucks at present.
> 
> Not sure I followed how to comment out the screen saver...
> 
> ...


Change it to

```
//lcd.enableScreenSaver(30);
```
to ignore this line of code (turn into a comment).

To change the input so it does not suck, try changing Line 57 to 

```
GetIntField divfField(divideForm, "Divisions", 1, 1000, 1, 3, " ");
```

Working hours now so not playing with the script. if you get syntax errors, check the form example script for how to use it. I don't think there will be any flow on changes required.
NOte this code sets the maxiimum divisions to 1000.


----------



## rodw (Feb 18, 2015)

TorontoBuilder said:


> I am sure that it doesnt help that 6 degrees isnt equally divisible by the 0.36 deg /step if I change div /rotation to 1000



It will have much better accuracy as it is using floating point not integers and the numbers used are much larger, thus add to the accuracy. 

But you are correct. If you want equal divisions, do it by the numbers! That's why I think it is better not to display the "of 62" when you've entered a degree.

The physical resolution of the stepper is always going to be a limitation.

But if you want to say drill a hole and want one exactly 24 degrees further around the circle, you should be able to do it (or as close as you can get subject to stepper resolution)


----------



## rodw (Feb 18, 2015)

Just one more comment about using an electronic dividing head. We are viewing the world through a new paradigm. We immediately start thinking about the rotary table with an old world view that was around dividing controlled by dividing plates in discrete steps around a circle.

Moving to the world of electronics, we can break that paradigm and be more flexible and do different things (like pick an arbitrary angle to move). So maybe think of it in terms of:
Doing it by the numbers replicates the dividing plates. 
Doing it by degrees replicates winding the rotary table handle an arbitrary amount.

However in all cases, we are constrained by the physical limitations of the number handling in the software code and by the minimum angle a stepper can move. 

I wanted to totally avoid floating point maths but found I had to use it otherwise I got rounding errors when using purely integer maths. I therefore just use floating point maths when calculatiing ratios but store results as integer values as that is how the hardware is. That explains the heavy use of C casts to convert from one number type to another in places.


----------



## rodw (Feb 19, 2015)

Just implemented the 2 changes we have discussed

In *enterDegrees* change the way divisions is calculated

```
divisions = (long)((float) MINUTES_IN_CIRCLE / (float) angleField.value());
```

So now a 6 degree division will show as 60 degrees. This has no affect on the division code, just fixed the display  where it said "of 62" (now says "of 60")

Changed the definition of *divfField* in the global definitions to use GetIntfield a different data entry routine to support arbitrary divisions by cursoring along left to right.

```
Form divideForm(lcd);
GetIntField divfField(divideForm, "Divisions", 1000, GETINTFIELD_READ_WRITE);
```

The other issue raised was difficulty in entering an angle. This was a known feature as opposed to a bug. The correct way to enter an angle has been outlined above. If you want to improve the code, contributions would be accepted. The code resides in the LCD library *DegreeField.cpp*
in this procedure

```
int DegreeField::dispatch(int event)
```

If you are editing a library file, the best way I've found is to use an external code editor so you can edit it directly and then compile in the Arduino IDE. Google "free code editor" and there are heaps. I use Dreamweaver but its not free.


----------



## rodw (Feb 19, 2015)

Well  I have got the Home position and a speed control done now. Need to clean up the code and double check it all before posting it up tomorrow.

I have made the code think in terms of frequency in Herz for speed control. Quite tricky because a high frequency is a short time delay. kinda the inverse
This  will make it easy to set the parameters according to a data sheet.


----------



## rodw (Feb 19, 2015)

Well,

I think this is working. I've had a few dead ends
New features:
1. Sign on Screen moved to setup so it is not in the main menu (displays for 2 seconds)
2. Arbitrary input of  # divisions
3. New feature Set/Goto Home
4. New feature Set speed

I've made massive changes to achieve this so there could be bugs
The setup code has changed significantly so study the code before configuring it again to suit your hardware. TIMER_DELAY is unchanged but is now a  variable.



```
#define STEPPER_STEPS_REV 200 // The number of steps per stepper
#define MICRO_STEPS 10        // set to 1 if not not using a microstepper driver, otherwise set to # microsteps
#define DIVIDE_RATIO 90       // The Dividing table ratio (eg 40 or 90)
#define STEPS_PER_REV STEPPER_STEPS_REV * MICRO_STEPS * DIVIDE_RATIO 
#define NUMBER_JOG_STEPS 10L  
#define MAX_STEPPER_HZ  1000 // Maximum frequency for this stepper
#define MIN_STEPPER_HZ   400 // Minimum frequency for this stepper

long TIMER_DELAY = 80;
```

You can see I have added changes so the stepper speed parameters are defined in Hz.

*<Set Speed>*
picks a percentage range between

```
#define MAX_STEPPER_HZ  1000 // Maximum frequency for this stepper
#define MIN_STEPPER_HZ   400 // Minimum frequency for this stepper
```

and increments/decrements in 5% steps

There are procedures to convert between Hz and microseconds used internally to manage the frequency.

Default speed value (TIMER_DELAY = 80) is 37.5% of the default range I have set in the defaults

```
long TIMER_DELAY = 80;
```
So when using speed control for the first time, it will be truncated to 37% and will change. I may change he way this is done so it is aligned with a 5% increment and specify the default in Hz.


*<Home>*
The code should take the shortest route to the home position as it tests to se if tests to see if the current position is < 180 degrees. (I hope) So it will turn clockwise or anticlockwise to get home the fastest.

The home position defaults to the starttup position so to test, use in conjunction with the jog feature.

Hope I've explained enough. I had a few unexpected compiler issues so it is possible we have a stack overflow but it seems to have settled down now.

I need to get this installed on my rotary table to debug the speed and stepper control as I am uncertain if I've got it done right 

View attachment RotaryTableChuck3.zip


----------



## canadianhorsepower (Feb 19, 2015)

rodw said:


> Well,
> 
> I think this is working. I've had a few dead ends
> New features:
> ...


 
thanks for your GRATE integration to this:bow::bow:
At this point is it ready to do a straight download to the arduino board and
work  cheers

Luc


----------



## rodw (Feb 19, 2015)

canadianhorsepower said:


> thanks for your GRATE integration to this:bow::bow:
> At this point is it ready to do a straight download to the arduino board and
> work  cheers
> 
> Luc



Luc, I think so. Testing by a few others would be great!

I don't envisage adding any more features to the program. My next job is to mount up a stepper to my rotary table so I can use it and make sure the home and speed controls work OK. I won't be doing any more to it until then.

If I did anything more, it would be to add a Setup page so the parameters could be overwritten and saved to EEPROM without recompiling. That would let you use the one controller with multiple devices.


----------



## TorontoBuilder (Feb 19, 2015)

rodw said:


> Luc, I think so. Testing by a few others would be great!
> 
> I don't envisage adding any more features to the program. My next job is to mount up a stepper to my rotary table so I can use it and make sure the home and speed controls work OK. I won't be doing any more to it until then.
> 
> If I did anything more, it would be to add a Setup page so the parameters could be overwritten and saved to EEPROM without recompiling. That would let you use the one controller with multiple devices.



I'll test it later tonight.... great work. Seriously. If I ever get to Oz I owe you a beer, but you'd have to come to Sidney to collect


----------



## rodw (Feb 19, 2015)

TorontoBuilder said:


> I'll test it later tonight.... great work. Seriously. If I ever get to Oz I owe you a beer, but you'd have to come to Sidney to collect



Sounds like a plan.

I'm not that great with drawing stuff but the attached metric drawing should allow you to mount a NEMA23 stepper motor to a Vertex Rotary Table using 4 standoffs with a M5 thread at one end and a M5 hole tapped in the other. Make standoff length to suit your setup. PLate will bolt to Rotary table with M5 bolts and the stepper secured to standoffs using M5 screws.

My Weekend project. 

View attachment NEMA23 to Vertex Rotary Table.PDF


----------



## TorontoBuilder (Feb 19, 2015)

Within my given limitations i.e. no rotary table attached, v3 works for me.. 

I'm liking it very much.


----------



## rodw (Feb 19, 2015)

TorontoBuilder said:


> Within my given limitations i.e. no rotary table attached, v3 works for me..
> 
> I'm liking it very much.



Cool, is it just me or does it require 2 keystrokes to exit from a procedure? Please let me know.

I have tested it with a rotary table attached and holding the stepper in position by hand and it worked. If it moved off centre, I got missing steps so I need to get it properly mounted up myself to continue. 

Just one tip. When you engage and lock the worm, don't rotate it too much before locking it or it can bind. I've read this advice in a few places now, but I learnt the hard way....


----------



## TorontoBuilder (Feb 19, 2015)

rodw said:


> Cool, is it just me or does it require 2 keystrokes to exit from a procedure? Please let me know.
> 
> I have tested it with a rotary table attached and holding the stepper in position by hand and it worked. If it moved off centre, I got missing steps so I need to get it properly mounted up myself to continue.
> 
> Just one tip. When you engage and lock the worm, don't rotate it too much before locking it or it can bind. I've read this advice in a few places now, but I learnt the hard way....



Yes 2 keystrokes to exit procedure.

Im getting some weird issues when inputting number of divisions. The menu doesnt clear upon switching to the inout screen.

Also, getting very long lag time on the steps


----------



## Scott_M (Feb 19, 2015)

Rod
Thanks a bunch.
I will hack my 4th axis tomorrow and check it out on my machine. I played with it on the bench and all looks good.
I'll give a full report tomorrow.

Again thanks for all your effort ! Above and beyond.

Scott


----------



## rodw (Feb 19, 2015)

TorontoBuilder said:


> Yes 2 keystrokes to exit procedure.
> 
> Im getting some weird issues when inputting number of divisions. The menu doesnt clear upon switching to the inout screen.
> 
> Also, getting very long lag time on the steps



I've  had similiar issues with that input screen. It could be my code in the class, or it could be a stack overflow. Still got 1.5k free though which seems heaps. I tried to free up space by moving some form declarations to procedures but it did not like it.. 

Lag time could be a config error on the time delay. I noticed your micro stepper must be slower than my Gecko As you slowed it down from my original settings to get it working. I'm using a UNO. What board have you got?


----------



## TorontoBuilder (Feb 19, 2015)

rodw said:


> I've  had similiar issues with that input screen. It could be my code in the class, or it could be a stack overflow. Still got 1.5k free though which seems heaps. I tried to free up space by moving some form declarations to procedures but it did not like it..
> 
> Lag time could be a config error on the time delay. I noticed your micro stepper must be slower than my Gecko As you slowed it down from my original settings to get it working. I'm using a UNO. What board have you got?



I have Uno r3 compatible from sainsmart. Tomorrow I'll load the sketch on my other Uno and see if its has similar response time.


----------



## rodw (Feb 20, 2015)

Success! Well some anyway!

I have to remake a part for my Rotary table mount as the stepper is misaligned and binding. Something moved and I lost a setup so mustn't have got it in position again. But I did get the stepper mounted well enough to do some tests. 

I've seen a couple of the faults TorontoBuilder saw so I will look at that. It seems reentering the <divide #> a second time causes this.

I just had a look at the code in the LCD library and this is interesting and applies to the call to  mainForm.show();


```
*  Shows the form, or does nothing if the form is already on-screen.
 *
 * When the form is shown, the screen will be cleared and the currentField()
 * will be drawn.
 *
 * If the form was previously hidden, then the field that was previously
 * current will be shown again.  Call defaultField() before show() to reset
 * the form to show the first field instead.
```

So maybe we should be redawing the screen after a data entry procedure that does not use the form library.

It looks I also left some debugging print statements in the goHome() procedure that can be removed.

The good news is that I set the #divisions to 3 and after 3 steps of 120 degrees, I was exactly back where I started according to the Rotary table dial! Nice!

I have not checked the Go Home feature yet.

The number of steps in a single step jog needs to be a lot higher with a 90:1 stepper. If we can get the speed control sorted out, slow speed, continuous jogging should be all that's needed to position exactly.


----------



## rodw (Feb 20, 2015)

Sorted the corrupt display. Add this 

```
divideForm.defaultField();
```
before

```
divideForm.show();
```

Need to do this for all other forms


----------



## rodw (Feb 20, 2015)

Well, here is a quick update which fixes a few things.
1. Deleted debug printing statements
2. Fixes corrupt screen in some procedures when selecting them again.
3. Prints messages when going to and setting home so it is more obvious what's going on.

I don't understand why we need to hit select twice to exit a procedure but nobody has complained about it.  

View attachment RotaryTableChuck4.zip


----------



## rodw (Feb 20, 2015)

Oops, missed a bug which meant degrees were wrong when dividing # in the last upload

Change the enterDivisions() code to this


```
void enterDivisions(void)
{
  long tmpDeg;
  float tmpSteps = (float) STEPPER_STEPS_REV * (float)MICRO_STEPS * (float)DIVIDE_RATIO;
  tmpDeg=(long)((float)MINUTES_IN_CIRCLE / (float)divisions);
  divfField.setValue(divisions);
  divideForm.defaultField();
  divideForm.show();
  while(1){
    int event = lcd.getButton();
    if(event == LCD_BUTTON_SELECT)
      break;
    if (divideForm.dispatch(event) == FORM_CHANGED) {
        if (divideForm.isCurrent(divfField)) {
          // set the number of divisions here
          divisions = divfField.value();        
          tmpDeg=(long)((float)MINUTES_IN_CIRCLE / (float)divisions);
          stepsPerDiv = (long)( tmpSteps *((float) tmpDeg/(float)MINUTES_IN_CIRCLE));
         }
    }
  }
  goDivide(tmpDeg);
}
```


----------



## rodw (Feb 20, 2015)

There are still a few bugs in the divisions and angle procedures, I am working on. A few of them got introduced when I changed the configuration data #defines which interfered with the casts between data types. I'll do a bit more checking.


----------



## rodw (Feb 20, 2015)

I decided to post up another version with most of the bugs sorted.
Also solved the two keystrokes to exit problem  

View attachment RotaryTableChuck4.zip


----------



## TorontoBuilder (Feb 20, 2015)

rodw said:


> There are still a few bugs in the divisions and angle procedures, I am working on. A few of them got introduced when I changed the configuration data #defines which interfered with the casts between data types. I'll do a bit more checking.



Rod, You're awesome. Thanks for working so hard on this.


----------



## canadianhorsepower (Feb 20, 2015)

rodw said:


> I decided to post up another version with most of the bugs sorted.
> Also solved the two keystrokes to exit problem


 
Thanks for this Rod  Thm:Thm:

do we still have to import the LCD library from post 20

cheers

Luc


----------



## Scott_M (Feb 20, 2015)

Hi Rod

I hacked into my 4th axis and ran from the arduino. Power from the mill and step/direction and 5V from the arduino. This is a 6" Tormach 4th. It has a Nema 23 motor. Running at 65 volts with a current limiting resistor for 2 amps.
It ran well, I bumped the speed up to 100.
You are correct , single steps are really small , it really takes a bunch to move a degree.

I ran into a error when trying to move a specified 30 degrees. It was turning 180. I took some shaky handheld video.

www.sdmfabricating.com/upload_page/RodV4.MOD 

With the exception of the math error it is very cool !

Or maybe it was remembering the previous input of 2 in # divisions ?
The screen did say "of 12" when I had it set to 30 degrees on the DMS page.

Scott


----------



## Scott_M (Feb 20, 2015)

More info

I tried to reproduce the bug and it is reproducible. But I am not sure it is a problem if you know about it and I am not sure anyone would do this.
Step 1 boot up, set number of divisions to 2 and go, it will go to 180. hit it again it will continue on to 0
step 2 select out and select to "set angle" enter 030.00.00 and go, it will go to 180

I do not think a real world situation would have you entering data like that. It would be either all degrees or divisions.
And if you have too switch , reboot and start fresh.

I did enter 10.00.00 and it went  10 and then reentered 30 and it went another 30 to 40 so that works fine.

"Home" works good. If you do not set a home position it will go to where it was when you booted up.

Very,very nice Rod !!  well done.

Scott


----------



## TorontoBuilder (Feb 20, 2015)

rodw said:


> I decided to post up another version with most of the bugs sorted.
> Also solved the two keystrokes to exit problem



runs on mine... 2 keystroke issue indeed solved.


----------



## chucketn (Feb 20, 2015)

Although it compiled without error this time, I cannot get ver4 to run on my hardware. I do have all the libraries required, and changed the step and direction pins to match my setup. I reloaded Chuck F's sketch and it works so no hardware issues. The menus come up and work but the stepper, she no move!.

Chuck


----------



## Scott_M (Feb 20, 2015)

chucketn said:


> Although it compiled without error this time, I cannot get ver4 to run on my hardware. I do have all the libraries required, and changed the step and direction pins to match my setup. I reloaded Chuck F's sketch and it works so no hardware issues. The menus come up and work but the stepper, she no move!.
> 
> Chuck


 
Chuck
I do not think you can change the sketch to work with your hardware. Rod moved the step pin from 3 to 1 because there was a conflict with pin 3.

Not entirely sure but that is my guess.

Scott

Edit;  I just checked the LCD library and the "backlight" pin is pin 3


----------



## chucketn (Feb 20, 2015)

I'm not having a problem with the LCD, it displays the menu options and I can set the # of divisions. Just the stepper not working. I can hear the stepper buzz, and it kinda twitches when the movement ends.
I guess if I want it to work, I need to go through both sketches side by side and find where the settings are different for the stepper.

Chuck


----------



## Scott_M (Feb 20, 2015)

Chuck

Pin 3 is being used already by something else. By you trying to use it as well is a "conflict" it is not going to work correctly.
You won't find the pin conflict in the sketch. It is in the LCD library and cpp file.

I do not know enough about this stuff to know if you can alter that library without major issues.

I think you would be much better off moving the step pin to pin 1.

Scott


----------



## rodw (Feb 20, 2015)

Scott_M said:


> More info
> 
> I tried to reproduce the bug and it is reproducible. But I am not sure it is a problem if you know about it and I am not sure anyone would do this.
> Step 1 boot up, set number of divisions to 2 and go, it will go to 180. hit it again it will continue on to 0
> ...



Scott, thanks I'll have a look. I'm trying to keep the steps and angles remembered between the  #steps and Angle functions so I don't have to write separate stepping routines for each method (to save memory). I will have missed a conversion somewhere. I thought I'd got them all.

Great to know we have one actually driving a rotary table


----------



## rodw (Feb 20, 2015)

chucketn said:


> I'm not having a problem with the LCD, it displays the menu options and I can set the # of divisions. Just the stepper not working. I can hear the stepper buzz, and it kinda twitches when the movement ends.
> I guess if I want it to work, I need to go through both sketches side by side and find where the settings are different for the stepper.
> 
> Chuck



Chuck, I think you'll have the speed/frequency configuraton in the #defines set too fast for your stepper. I've got it set for 2000 steps per stepper revolution. If you have a conventional stepper driver (like the Polou) you need to make some changes.

ie here

```
#define STEPPER_STEPS_REV 200 // The number of steps per stepper
#define MICRO_STEPS 10        // set to 1 if not not using a micostepper driver, otherwise set to # microsteps
#define DIVIDE_RATIO 90       // The Dividing table ratio (eg 40 or 90)
```

probably here, where I changed it to 1 for you

```
#define MICRO_STEPS 1        // set to 1 if not not using a micostepper driver, otherwise set to # microsteps#define MICRO_STEPS 10        // set to 1 if not not using a microstepper driver, otherwise set to
```

Once you get this right, if you still have a problem, increase this number to slow down the stepper (eg. Increase the time between stepper pulses).


```
long TIMER_DELAY = 80;
```


----------



## rodw (Feb 20, 2015)

Scott_M said:


> Chuck
> 
> Pin 3 is being used already by something else. By you trying to use it as well is a "conflict" it is not going to work correctly.
> You won't find the pin conflict in the sketch. It is in the LCD library and cpp file.
> ...



Correct, the pins used by the Freetronics board are:
*3, 4, 5, 6, 7, 8, 9 and Analog 0*

This meant I had to move one of the stepper signals off Pin 3


----------



## rodw (Feb 20, 2015)

canadianhorsepower said:


> Thanks for this Rod  Thm:Thm:
> 
> do we still have to import the LCD library from post 20
> 
> ...



Luc, you only need to import the additional libraries once. If you've done it before, you don't need to do it otherwise, yes do it. My edited post #1 will clarify this.

PS the compiler will be very unhappy and tell you if code is missing via a stream of errors...


----------



## rodw (Feb 20, 2015)

TorontoBuilder said:


> Rod, You're awesome. Thanks for working so hard on this.



Thanks more than happy to test your hardware in return


----------



## rodw (Feb 20, 2015)

Scott_M said:


> Hi Rod
> 
> I ran into a error when trying to move a specified 30 degrees. It was turning 180.
> Scott




Scott, it will be a while before I can test this with a stepper but for now, try replacing *enterDegrees()* with this:

```
void enterDegrees(void)
{
  int event = LCD_BUTTON_NONE;
  float tmpSTEPS_PER_REV = (float)STEPPER_STEPS_REV * (float)MICRO_STEPS * (float)DIVIDE_RATIO;
  angleField.setValue(mAngle);
  if(mAngle){
     divisions = (long)((float) MINUTES_IN_CIRCLE / (float) mAngle); 
     stepsPerDiv = (long)(tmpSTEPS_PER_REV *((float)mAngle/(float)MINUTES_IN_CIRCLE));
  }   
  else{
     divisions = 0L;  
     stepsPerDiv = 0L;
  }
  angleForm.defaultField();
  angleForm.show();
  while(event!= LCD_BUTTON_SELECT){
    event = lcd.getButton();
    if(event == LCD_BUTTON_SELECT)
      break;
    if (angleForm.dispatch(event) == FORM_CHANGED) {
        if (angleForm.isCurrent(angleField)) {
          // set the number of divisions here
          mAngle = angleField.value();
          stepsPerDiv = (long)((float)tmpSTEPS_PER_REV *((float)mAngle/(float)MINUTES_IN_CIRCLE));
          divisions = (long)((float) MINUTES_IN_CIRCLE / (float) angleField.value()); 
        }
    }
  }
  if(mAngle)
    goDivide(angleField.value());
}
```

Looks like I was not initialising stepsPerDiv on entry to agree with the angle and I've also changed the code to make sure STEPS_PER_REV is a float before it it used


----------



## canadianhorsepower (Feb 20, 2015)

rodw said:


> Thanks more than happy to test your hardware in return


 
Rod
I must be real stupid can't fixe that LCD error:wall::wall::hDe::hDe::wall::wall:

can you walk me thrue this  PLZ

Luc


----------



## darkoford (Feb 20, 2015)

rodw said:


> Correct, the pins used by the Freetronics board are:
> *3, 4, 5, 6, 7, 8, 9 and Analog 0*
> 
> This meant I had to move one of the stepper signals off Pin 3



Is it the pin (red)?

// Pins in use
#define BUTTON_ADC_PIN           A0  // A0 is the button ADC input
#define LCD_BACKLIGHT_PIN         3  // D3 controls LCD backlight
// ADC readings expected for the 5 buttons on the ADC input
#define RIGHT_10BIT_ADC           0  // right
#define UP_10BIT_ADC            145  // up
#define DOWN_10BIT_ADC          329  // down
#define LEFT_10BIT_ADC          505  // left
#define SELECT_10BIT_ADC        741  // right
#define BUTTONHYSTERESIS         10  // hysteresis for valid button sensing window
//return values for ReadButtons()
#define BUTTON_NONE               0  // 
#define BUTTON_RIGHT              1  // 
#define BUTTON_UP                 2  // 
#define BUTTON_DOWN               3  // 
#define BUTTON_LEFT               4  // 
#define BUTTON_SELECT             5  // 
//some example macros with friendly labels for LCD backlight/pin control, tested and can be swapped into the example code as you like
#define LCD_BACKLIGHT_OFF()     digitalWrite( LCD_BACKLIGHT_PIN, LOW )
#define LCD_BACKLIGHT_ON()      digitalWrite( LCD_BACKLIGHT_PIN, HIGH )
#define LCD_BACKLIGHT(state)    { if( state ){digitalWrite( LCD_BACKLIGHT_PIN, HIGH );}else{digitalWrite( LCD_BACKLIGHT_PIN, LOW );} }
/*


----------



## rodw (Feb 20, 2015)

canadianhorsepower said:


> Rod
> I must be real stupid can't fixe that LCD error:wall::wall::hDe::hDe::wall::wall:
> 
> can you walk me thrue this  PLZ
> ...



Which LCD error?

Try this. 
1. Download LCD.zip
2. Unzip
3. Manually move the folder to your Arduino Library folder.
4. Restart the Arduino IDE

In my system, the library is in
\Documents\Arduino\libraries


----------



## rodw (Feb 20, 2015)

darkoford said:


> Is it the pin (red)?
> 
> // Pins in use
> #define BUTTON_ADC_PIN           A0  // A0 is the button ADC input
> ...



Yes, I started using pins 2&3 like Chuck when I first started with steppers but as soon as I added the LCD shield, I had a conflict so moved the signal on pin 3 to pin 1 and my code will always reflect that change.

If your backlight is on a different pin, change the #define you've highlighted.


----------



## TorontoBuilder (Feb 20, 2015)

rodw said:


> Correct, the pins used by the Freetronics board are:
> *3, 4, 5, 6, 7, 8, 9 and Analog 0*
> 
> This meant I had to move one of the stepper signals off Pin 3



Okay so I dont have a stepper driver hooked up yet, so maybe this is why I'm not getting conflict when I have changed the stepPin to pin 3

I'm really not sure what you mean when you say freetronics uses pin 3, what does it use pin 3 for? I know that Freetronics uses the same pins as the sainsmart LCD; 8, 9, 4, 5, 6, 7 and A0 for the buttons. 

If I cant change the software i cant use the 3 boards I just ordered... without hacking up the board to cut traces anyway


----------



## rodw (Feb 20, 2015)

TorontoBuilder said:


> Okay so I dont have a stepper driver hooked up yet, so maybe this is why I'm not getting conflict when I have changed the stepPin to pin 3
> 
> I'm really not sure what you mean when you say freetronics uses pin 3, what does it use pin 3 for? I know that Freetronics uses the same pins as the sainsmart LCD; 8, 9, 4, 5, 6, 7 and A0 for the buttons.
> 
> If I cant change the software i cant use the 3 boards I just ordered... without hacking up the board to cut traces anyway



I don't think its an issue to worry about if this is the LCD board you have
http://www.sainsmart.com/sainsmart-...rduino-duemilanove-uno-mega2560-mega1280.html

Looks like Sainsmart and Freetronics use the same pins for the LCD and the same resistor values for the buttons but use a different method for enabling the backlight.

I pulled down the zip file and the PDF diagram shows Sainsmart has hardwired the backlight. Freetronics uses Pin 3 so you can turn it on and off from within the sketch.

For Sainsmart users it would be a good idea to change the #define darkoford found to point to an unused pin so the LCD library does not send spurious signals to your stepper!


----------



## rodw (Feb 20, 2015)

So tell me again why I'm writing this software?







I started with a square piece of 6mm aluminium same size as the stepper, centred it under the mill spindle and drilled all the holes using the PCD function.  I also used the tapping feature of my SX3 mill to thread the holes.

Complete kit and the collar from the Rotary table.





And here it is attached to my 6" Vertex Rotary table






So now I got this far, the left button on my display has died and starts pressing buttons all on its own....

It was changing direction in front of my eyes half way through a divisions. So I need to make sure the direction cannot be changed while doing dividing steps.


----------



## TorontoBuilder (Feb 20, 2015)

rodw said:


> So tell me again why I'm writing this software?
> 
> 
> 
> ...



That looks like a great set-up. 

Does this look like a vertex rotary table? The vendor doesn't list the manufacturer... 

http://www.accusizetools.com/horizontal-vertical-precision-rotary-table/


----------



## TorontoBuilder (Feb 20, 2015)

rodw said:


> I don't think its an issue to worry about if this is the LCD board you have
> http://www.sainsmart.com/sainsmart-...rduino-duemilanove-uno-mega2560-mega1280.html
> 
> Looks like Sainsmart and Freetronics use the same pins for the LCD and the same resistor values for the buttons but use a different method for enabling the backlight.
> ...



That's the LCD shield I have, and what I modeled my own boards after, except I may use a serial interface and need to substitute a different lcd library


----------



## rodw (Feb 20, 2015)

TorontoBuilder said:


> That's the LCD shield I have, and what I modeled my own boards after, except I may use a serial interface and need to substitute a different lcd library



I don't think that will be an issue. Just modify the LCD class to use your board. You'll see internally LiquidCrystal.h is used. I am no expert but I think a serial interface display will just substitute different Liquidcrystal code.

The real smarts in the libraries used is in the keyboard handling and that is all on the analog port. That is configurable in LCD.h


```
#define LCD_BUTTON_PIN          A0       // Button state is on A0
```

I found a bug. If you just accept the default value of 3 in #steppers, nothing happens (with stepper connected) as I'm not initialising the steps per division. Working on it....


----------



## rodw (Feb 21, 2015)

TorontoBuilder said:


> That looks like a great set-up.
> 
> Does this look like a vertex rotary table? The vendor doesn't list the manufacturer...
> 
> http://www.accusizetools.com/horizontal-vertical-precision-rotary-table/



Thanks, Looks very similar.  I got mine here so compare the dimensions
http://www.machineryhouse.com.au/R006
even the diagrams look the same.

Anyway, the mounting will be much the same I am sure. The collar is held on by two grub screws.

Pretty sure I've finished my debugging attached to a real  rotary table. Found a few things. I think it is good now.

Also added a new feature *<Jog Step>*
This lets you enter the step angle (in degrees) you want to use to jog the table round in single step mode. Defaults to 30 seconds (0.5 degrees).

I'll post up Version 5 soon.


----------



## rodw (Feb 21, 2015)

Ok Guys Here is the latest version. I think it is pretty clean now.

*New Features*
1. *<Jog Step>* - Allows you to set the angle for each step. Default 30 seconds (0.5 degrees)
2. *<Contin Turn>* - Turns continuously in the last direction selected. To select the direction, simply use *<Jog>* to choose the direction of travel

Tested on a 6" Vertex rotary table and seems to be working well. I've run the table with an electric drill, washed it out re-oiled and aligned the stepper. I've also run it continuously in both directions to bed the table in and it seems to be stepping reliably with quite a small stepper on a 19 volt laptop supply.

Let me know if there are any more bugs. I hope I've squashed them all. 

View attachment RotaryTableChuck5.zip


----------



## Scott_M (Feb 21, 2015)

Hi Rod

Your motor mount looks good  

Some weirdness with the latest code. Did you upload the wrong file ? it says 4. I changed it to 5 when I downloaded. I did not see the new features.
Also, a bunch of stuff does not work.
First thing I did was set home
then I went to divide# and left it at 3 neither the left or right buttons did any thing. did not move.
went to enter angle, entered 120 hit right and it went 120. Went to "home" and hit goto and it went forward to about 155 and stopped. hit it again and it went to 180 and stopped.

I will be setting up a job on the mill today that may take a week to finish so I may not be able to hook this up again for awhile.

Thank you so much for all your hard work !!

Scott


----------



## cwebs (Feb 21, 2015)

I have been running the other software from Chuck's posts for a couple years and have made parts using it. This is a great upgrade but will not run on my home made controller so I will make a new one. I have just got hold of a couple Pro-Micro boards and was wondering if there was any reason this software won't run on these boards. At $7 each it beats using an Uno. If not then I can perf board up an Atmaga328 and go that way. Thanks, Carl


----------



## canadianhorsepower (Feb 21, 2015)

rodw said:


> Which LCD error?
> 
> Try this.
> 1. Download LCD.zip
> ...


 
Hi Rod
her is what I get

thanks

Luc


----------



## TorontoBuilder (Feb 21, 2015)

cwebs said:


> I have been running the other software from Chuck's posts for a couple years and have made parts using it. This is a great upgrade but will not run on my home made controller so I will make a new one. I have just got hold of a couple Pro-Micro boards and was wondering if there was any reason this software won't run on these boards. At $7 each it beats using an Uno. If not then I can perf board up an Atmaga328 and go that way. Thanks, Carl



This version should work equally well on the Micro. I'd thought of using the micro myself but then settled on the nano for the onboard usb connection.


----------



## darkoford (Feb 21, 2015)

canadianhorsepower said:


> Hi Rod
> her is what I get
> 
> thanks
> ...




So you do not have a library of LCD.

You might not be well placed lcd.h a library.

At the beginning of the program have this:

#include <BoolField.h>
#include <DegreeField.h>
#include <Field.h>
#include <Form.h>
#include <IntField.h>
#include <LCD.h>
#include <ListField.h>
#include <TextField.h>
#include <TimeField.h>
#include <GetIntField.h>
#include <TimerOne.h>

And on the hard disk directory "Arduino" you need to set up a library of the lcd.h:




Link is in post # 20 for LCD and TimerOne.


----------



## canadianhorsepower (Feb 21, 2015)

darkoford said:


> So you do not have a library of LCD.
> 
> You might not be well placed lcd.h a library.
> 
> ...


 
I do have that at the top of my program:wall::wall:
I can't see your picture clearly
Can someone email me the program
I'll try it on another computor

Thanks


----------



## rodw (Feb 21, 2015)

Scott_M said:


> Hi Rod
> Some weirdness with the latest code. Did you upload the wrong file ? it says 4. I changed it to 5 when I downloaded. I did not see the new features.
> Also, a bunch of stuff does not work.
> 
> ...




Ooops Sorry. It was the wrong file. Rather than add yet another file to confuse people, I have put the right file on Post #108

http://www.homemodelenginemachinist.com/showpost.php?p=262304&postcount=108

If the file name ends in 4, refresh your browser as it is now
RotaryTableChuck5.zip


----------



## rodw (Feb 21, 2015)

canadianhorsepower said:


> Hi Rod
> her is what I get
> 
> thanks
> ...




Luc, I've had similar problems getting libraries installed. Try moving the LCD folder out of the libraries and arduinos folders and from the Arduino IDE, try to add a new library.

Sketch/Import Library/New Library

Then navigate to the LCD folder

It will copy it to the Libraries folder and should update the config internally.

I'm sure if you google some stuff you'll get some tips to get this sorted.

Nothing to do with the code, just a configuration error at your end


----------



## rodw (Feb 22, 2015)

I started working on Version 6 of the controller which saves configuration data to the EEPROM and includes a data entry form to change the setup parameters.

The framework is now done.
1. Default data is created and saved to EEPROM if it does not exist.
2. Data is retrieved from EEPROM if it exists.
3. Designed to store multiple stepper setups so you can move the controller to multiple devices.
4. Data entry form is tested and working.
5. User is prompted to saves Changes to the EEPROM  (Yes/No)
6. Saving of changed data confirmed working.

But I still need to edit the sketch to actually use this configuration data!

I did get some stack overflow issues and the Form class is not particularly helpful here as it uses a String class and I can't see how to get it to recognise variables in program memory. I seem to have got enough memory for now so I think we'll make it without running out of dynamic memory as there is not much left to do.


----------



## cwebs (Feb 22, 2015)

TorontoBuilder said:


> This version should work equally well on the Micro. I'd thought of using the micro myself but then settled on the nano for the onboard usb connection.


 My Pro Micro are USB. Were you thinking of the Pro Mini? Carl


----------



## TorontoBuilder (Feb 22, 2015)

cwebs said:


> My Pro Micro are USB. Were you thinking of the Pro Mini? Carl



ah yeah, I was thinking of the mini. You should have no problem with the pro micro


----------



## cwebs (Feb 22, 2015)

Rod, did I find a bug or don't I understand correctly.  When I bring up "set Speed" and set a number, I then click on Select. When I go back to "Set Speed the number is about one half the previous setting. Go back to "Select" and back it halfed again. IE... I set speed to 70% /select/set speed/50%/select/set speed/28%/select/set speed/ 13%/select/ set speed/5%. Etc. Some times after boot my set speed is 0%.  Hope you understand what I am trying to point out.  Carl


----------



## cwebs (Feb 22, 2015)

Rod, just another thought. On my old RT controller I add an enable switch for the driver, and it came in very handy allowing me to turn the table using the hand wheel for quick setup and fine alignment. Also helps keep the stepper cooler when not in use for long time. Carl


----------



## rodw (Feb 22, 2015)

cwebs said:


> Rod, did I find a bug or don't I understand correctly.  When I bring up "set Speed" and set a number, I then click on Select. When I go back to "Set Speed the number is about one half the previous setting. Go back to "Select" and back it halfed again. IE... I set speed to 70% /select/set speed/50%/select/set speed/28%/select/set speed/ 13%/select/ set speed/5%. Etc. Some times after boot my set speed is 0%.  Hope you understand what I am trying to point out.  Carl



Carl, Thanks. I got all the code rearranged so it uses the data stored in EEPROM last night and after that, I noticed that there was something strange happening in the speed control you mention but everything else is tested and working as expected.

I am rethinking my approach to speed control as now I can specify it in setup as well but both are currently entered in different ways. It's been good to be able to play with the speed on the fly. Its amazing to see how quick I can get the table to move (but at the expense of missing steps on Startup)

I also want to work on some speed ramp up ad ramp down code. I think there are 3 speed parameters:
1. Slowest Speed/Maximum torque
2. Fastest speed/minimum torque
3. Current Operating speed (normally the same as fastest speed but able to be overridden)

I finally found a good article about ramp Up and Ramp Down which says to start at the minimum and ramp up the speed with each stepper pulse until it gets to operating speed. On Ramp down, do the opposite starting before the end of the current movement so you finish at the slow speed. 



cwebs said:


> Rod, just another thought. On my old RT controller I add an enable switch for the driver, and it came in very handy allowing me to turn the table using the hand wheel for quick setup and fine alignment. Also helps keep the stepper cooler when not in use for long time. Carl



I have not got that far yet and am still using 2 power supplies (5V & 19V) but I'll remember that when it gets into a box. On my table the handwheel is gone though and it is hard to turn manually (hence the jog functions)! Using a stepper with a double ended shaft would let you put a hand wheel back on.


----------



## rodw (Feb 22, 2015)

For got to mention that I have added a feature to the Continuous turning mode so you can change direction on the fly with left/right buttons. I need to allow for ramp up and ramp down once it is done.


----------



## cwebs (Feb 22, 2015)

rodw said:


> Carl, Thanks. I got all the code rearranged so it uses the data stored in EEPROM last night and after that, I noticed that there was something strange happening in the speed control you mention but everything else is tested and working as expected.
> 
> I am rethinking my approach to speed control as now I can specify it in setup as well but both are currently entered in different ways. It's been good to be able to play with the speed on the fly. Its amazing to see how quick I can get the table to move (but at the expense of missing steps on Startup)
> 
> ...


 Handwheel is needed but on mine I have a 3:1 drive belt into an eight inch 90 turn table. I am using only a nema 17 stepper so I have a way to turn it by hand. Sounds under powered but I have loaded the table up with #70 and it turned with out loosing any steps. Thanks for your great work. Carl


----------



## rodw (Feb 22, 2015)

cwebs said:


> Handwheel is needed but on mine I have a 3:1 drive belt into an eight inch 90 turn table. I am using only a nema 17 stepper so I have a way to turn it by hand. Sounds under powered but I have loaded the table up with #70 and it turned with out loosing any steps. Thanks for your great work. Carl



Thanks for the encouragement. I ave a couple of Nema 17's here too but the mounting was easier with the NEMA 23.

Read ramp up stuff again. The algorithim will be:
Ramp up period is 20% of the division
Max speed period is 60% of the division
Ramp down is 20% of the division

we are going to talk Herz below but internally, we'll convert it to the timer interrupt delay (microseconds)
Lets assume a movement of 1,000 steps
1. Start at the specified (slow) starting speed (400 Hz is current default).
2. take 20% of the movement (200) steps
3.After each stepper pulse, reduce the timer delay by 1 microsecond for each of those 200 steps (speeding up), stopping if the maximum speed is reached (1000 Hz is current default).
4.Run at that speed for 600 steps (60%)
5.For the last 200 steps (20%), slow the stepper down by increasing the timer delay by 1 microsecond each step until it stops.

So on small movements we may never get to maximum speed but will always be accurate which is the goal!

I think for a microstepper, we should only change the speed for each full motor step (10 microsteps in the case of my Gecko)

Carl, your NEMA17 will thank me!


----------



## cwebs (Feb 23, 2015)

rodw said:


> Thanks for the encouragement. I ave a couple of Nema 17's here too but the mounting was easier with the NEMA 23.
> 
> Read ramp up stuff again. The algorithim will be:
> Ramp up period is 20% of the division
> ...


 _ I think that a set speed option in setup would be great. And, my nema 17 is waiting for your help. In ChuckF's skitch the speed defalt was s5 and my 17 didn't like that but ran great when I changed it to s1 or s2. _


_PS, hope your summer is going great for you. I am in Maine and it's the coldest winter in History. Tons of snow if you want some.  LOL  Carl_


----------



## John S (Feb 23, 2015)

Are you still looking for a drawing of the vertex mounting ?
I make these for a company but the drawing and design is mine so I don't mind sharing.


----------



## chucketn (Feb 23, 2015)

John S said:


> Are you still looking for a drawing of the vertex mounting ?
> I make these for a company but the drawing and design is mine so I don't mind sharing.


 
I'm sure many readers would find your drawing useful, if you wouldn't mind posting it, including me.

Chuck


----------



## Scott_M (Feb 23, 2015)

Hi John
Sure, I would like to see them. Thanks for sharing.

Scott


----------



## rodw (Feb 23, 2015)

John S said:


> Are you still looking for a drawing of the vertex mounting ?
> I make these for a company but the drawing and design is mine so I don't mind sharing.



John, thanks, I'm happy with my open cage design. Initially I was going to do it similar to yours but somebody talked me into a different design.

It would be great if you could share your drawings though.


----------



## John S (Feb 24, 2015)

OK will sort them out. Checked last night and the ones I have are not complete. I have a 'pattern' set I tend to copy for each batch so I know they work but as all drawings are at my expense and not the customers they tend to be either crude or not updated.


----------



## rodw (Feb 24, 2015)

John S said:


> OK will sort them out. Checked last night and the ones I have are not complete. I have a 'pattern' set I tend to copy for each batch so I know they work but as all drawings are at my expense and not the customers they tend to be either crude or not updated.



John, is this your design for the vertex tables?







I drew up a variant of this where the flange was bolted to a cylinder. Initially, I wanted to see if I could put the mounting bolts on the outside but found there is not enough room and they need to be mounted internally as per this example.

Its actually quite a good exercise in using a a rotary table for the newcomer as  the bolt holes can be positioned by dividing so everything is concentric to the stepper shaft.

The key measurements for the Vertex are:
Outer diamater to match vertex collar: 56mm
Centre bore for table shaft: 21mm dia
Main cylinder bore: 43mm (ensure clearance for internal mounting bolt heads)
3 x holes for M5 mounting bolts to the table collar: 5.1 mm dia on PCD of 32 mm
4 x M5 tapped holes for NEMA 23 mount on flange: 4.2mm dia on PCD of 66.66 mm (start at 45 degrees).

Length - to suit your stepper (mine has a long shaft)
Slot cylinder to access shaft coupling screws.
Flange side: match NEMA23 dimensions: 56.4mm


----------



## Scott_M (Feb 24, 2015)

rodw said:


> Slot cylinder to access shaft coupling screws.


 
I have seen a few mounts where people put great big holes in the side of the mount to get at the coupling screws.
On my 4th axis there is 1 pipe plug. You mount the coupling on one of the shafts and tighten it's screw. Then turn the shaft so it aligns with the one hole in the mount and insert the mount and line the coupling up with the other shaft tighten the coupling through the hole. And then finish tightening the mount.

You really only need access to one of them. 

Scott


----------



## John S (Feb 24, 2015)

Yes Rod, they are my design. There are only two parts, the flanged tube although that does have a pressed in steel mounting flange with the 21 mm hole in it and the actual steel stepper mounting.
It's done this was as the three bolts holding the tubs on never sit in the same position table to table, it depends on the mesh of the worm.
But if the flange is separate then you can always get the motor to sit square.

I also convert table for about 4 companies as well. Not all Vertex.


----------



## rodw (Feb 25, 2015)

John S said:


> Yes Rod, they are my design.
> It's done this was as the three bolts holding the tubs on never sit in the same position table to table, it depends on the mesh of the worm.
> But if the flange is separate then you can always get the motor to sit square.



Interesting, so just loosening the grub screws on the Vertex collar and turning the assembly does not give enough adjustment? This is how I aligned mine, but it's only one table 

It looks like I've finally got the software ramping up and down the speed correctly. Still need a bit of cleaning up the code before I get it back on the rotary table. I need to do that before I know I've  succeeded as I'm not sure if it is OK to change the interrupt timer delay in the middle of an Interrupt Service routine. 

I've been caught a couple of times where perfectly legal C code in an if() statement does not work as expected on the Arduino. Creating the value in a variable and then testing it in the if() statement then works fine. Very frustrating!

I think the algorithim I 'm using for short steps where the number of pulses are insufficient to ramp up to full speed  needs to be changed. I'm using (20% ramp up, 60% running, 20% ramp down). I think it should be closer to 45%% ramp up, 10%  running, 45% ramp down to maximise performance.

It'll be fun playing with the settings to see if speed on a soft start can be increased past the current limits I've observed.


----------



## John S (Feb 26, 2015)

My tubes don't fit by the collar, they fit using the three existing tapped holes when the dial assembly is removed.
Don't think I have a vertex unit here but my girlfriend has one and I'm up there at the week end so I'll strip it, take some pictures and measurements and post early next week.


----------



## rodw (Feb 26, 2015)

John S said:


> My tubes don't fit by the collar, they fit using the three existing tapped holes when the dial assembly is removed.
> Don't think I have a vertex unit here but my girlfriend has one and I'm up there at the week end so I'll strip it, take some pictures and measurements and post early next week.



John real appreciate your input in the hardware. It will be good to have it here with the software.



cwebs said:


> _ I think that a set speed option in setup would be great. And, my nema 17 is waiting for your help. In ChuckF's skitch the speed defalt was s5 and my 17 didn't like that but ran great when I changed it to s1 or s2. _
> [/I]



I still need to do a bit more debugging but have made some great progress on the soft start/ramp up code. It is working fine when dividing and it appears the stepper can be driven faster. 

Its been a bit tricky to get the speed to ramp down in continuous and constant jogging modes. For some reason, it won't work until the code s called once, and then it works fine. I have  to work out what gets initialised.

I was starting it from 400 Hz and ramping up to 12000 Hz with a NEMA 17 and the little stepper sounds like a jet engine coming to life! Its interesting to watch in continuous mode when you change direction. It slowly stops before ramping up to speed in the reverse direction. (400 is to slow as it takes quite a while to get to speed.

I guess you guys will want  video....


----------



## rodw (Feb 26, 2015)

Well, here it is. Main New features are:
1. Stepper ramps up and ramps down from/to Max Stepper Frequency
2. All defaults saved in EEPROM memory

This version saves all defaults to the EEprom. This has required an additional header file which is included in the zip file. Copy into the Libraries folder (I put it in the LCD folder). This is one of the standard files available on the Arduino web site. See:
http://playground.arduino.cc/Code/EEPROMWriteAnything

Settings (including stepper and direction pins, minimum frequency and maximum frequency) are stored.  "Max Stepper Hz" and "Min Stepper Hz" control the speed the stepper starts to ramp up from and also the maximum running speed. These defaults can be edited in the <Setup> Menu.

There is a "Save Settings?" option in the setup menu. If this is set to "Yes", the defaults are written to EEPROM when you press select to exit the menu. If you just want to try settings without saving them, leave it set to "No". You can go back into the setup menu and save them later.

Note the timer Delay is no longer used to control stepper speed but it still remains in the setup menu. Ignore it.

The speed control has been removed in this version.
Speed is controlled by the "Max Stepper Hz". You'll probably want to put the "Min Stepper Hz" to around 1000 as at 400, it is very slow to ramp up. I'll probably add it back in but you can control speed by changing  "Max Stepper Hz". Maybe try it at 10,000 but I was able to push it though to about 15,000. The good thing is you don't need to be tethered to a PC to make these changed as they are set in the user interface on the Arduino.

This is a massive rework and should allow you to get more out of your stepper. Bugs most likely abound. I did get some odd behaviour when it was wired up to my rotary table but I have made a lot of changes, since then and have not taken it back in the shed but have been running another stepper on the bench while coding.

I'l be interested to hear if this is kinder on NEMA17 stepper motors. 

View attachment RotaryTableChuck7.zip


----------



## RonGinger (Feb 26, 2015)

Where do I get all the rest of the libraries? The zip has only the main program and one .h file


----------



## rodw (Feb 26, 2015)

RonGinger said:


> Where do I get all the rest of the libraries? The zip has only the main program and one .h file



Ron,  if you go to the very first post, I've edited by adding a header that has a link to post #20 with all the prerequsites and the latest version which is updated every time I do an update.


----------



## cwebs (Feb 27, 2015)

Hi RodW, I am still having trouble with speed control in V7, as I did in V5. I am running V4 and V5 with all "Speed set" commented out and speed set TIMER_DELAY =100 in place of 80 and my Nema 17 is happy there. Keep up the great work. 

I also had to add the version number in the splash screen to keep track of witch version I am playing with. Had them all up at one time and got corn fused. Thanks, Carl


----------



## Scott_M (Feb 27, 2015)

Hi Rod
I had some time to play with V7, wow that is a bunch of code ! And most of it is way over my head   The previous versions I could mostly understand. Very impressive coding my friend.
I just hooked up to a stepper on my bench. The ramp up and down is very nice. I was able to run this nema 34 motor at 16000 max.
I did notice some odd behavior with go to home, I set home and then bumped a few steps (3) with the right button and then went back and went to "Go Home" and it continued in the same direction a few more steps and stopped. I am guessing about 7-8 steps from home. I tried a few other things with continuous turn a step but it seemed confused where home was.
Everything else seemed to work well. I may have time to hook it back up to my machine this weekend.

Here is a thought.. Would it be possible to control speed with a potentiometer ? I am pretty sure we have some analog pins free. That might make a nice feature. The pot min max would be what was used in setup.

Thanks again for all your hard work !!

Scott


----------



## rodw (Feb 27, 2015)

cwebs said:


> Hi RodW, I am still having trouble with speed control in V7, as I did in V5. I am running V4 and V5 with all "Speed set" commented out and speed set TIMER_DELAY =100 in place of 80 and my Nema 17 is happy there. Keep up the great work.
> 
> I also had to add the version number in the splash screen to keep track of witch version I am playing with. Had them all up at one time and got corn fused. Thanks, Carl



Great you have it going on your NEMA17. I would have thought V7 would let you sort the speed out from the Config menu. by increasing TIMER_DELAY, you are decreasing the stepper frequency. From memory, 80 is 6250 Hz so you need to take that down by 20%. I'd try the max freq at about 4000 and see how you go.

The version is a great idea. It keeps a 3 char signature internally in the EEPROM so it knows if there is any data stored or not. I should add an extra field for version number.

I'm now writing the device number on the start up screen. 
I've added code to create and add devices but need to add the select device code.



Scott_M said:


> Hi Rod
> I had some time to play with V7, wow that is a bunch of code ! And most of it is way over my head   The previous versions I could mostly understand. Very impressive coding my friend.
> I just hooked up to a stepper on my bench. The ramp up and down is very nice. I was able to run this nema 34 motor at 16000 max.
> I did notice some odd behavior with go to home, I set home and then bumped a few steps (3) with the right button and then went back and went to "Go Home" and it continued in the same direction a few more steps and stopped. I am guessing about 7-8 steps from home. I tried a few other things with continuous turn a step but it seemed confused where home was.
> ...



Scott, thanks for the feedback. It will inspire me to keep going! Hard to think the <200 lines of code I started with is now pushing 1000...

I think I will reenable the speed control in 5% increment between maxHz and minHz but not save it in eeprom which will give temporary control of speed that is wiped out on a reboot. If there is a speed you particularly like, you will be able to save the settings to EEProm as a separate device and retrieve it later.

A knob for speed control is a good idea. Not sure if it should be a pot or a rotary encoder though. The encoder could work just as the speed control is described above. a Pot might require calibration.



> And most of it is way over my head


kinda over mine too! heaps of trial and error.

When the stepper goes LOW, that is the end of a complete cycle (Hz) so thats when we change the speed.

When we want to move a given number of steps, We calculate the max and min timer delay
Then the number of frequency changes (in timer delay steps - microseconds) are calculated to go from the minimum frequency to the maximum frequency.
If there are not enough steps to go right up and then right back down, this number is altered to a lower number so the ramp up and ramp down fits to the available steps and the operating speed will not reach max Hz.

It then calculates pointers to endRampUp and StartRampDown. 
The #steps is decremented so endRampUp is a big number
so we start at min Hz and go up 1 delay setting on each step until we reach endRampUp, we go along at max speed until we get to StartRampDwn at which time we start slowing down. In theory, we should hit the minimum speed on the last step.



> I did notice some odd behavior with go to home, I set home and then bumped a few steps (3) with the right button and then went back and went to "Go Home" and it continued in the same direction a few more steps and stopped. I am guessing about 7-8 steps from home. I tried a few other things with continuous turn a step but it seemed confused where home was.


Scott, I did notice some issues with Home and will review it when I finish my changes and get it back on the rotary table. I am not sure if we are missing steps in the hardware or it is my code. The home tracking has not changed..

The other bug is that on continuous turning and continuous jogging, the rampdown when your finger off starts at max frequency, not the current frequency so that if it is turning very slowly, it will instantly leap to full speed, then ramp down. If you have a reasonable min Hz (say 1000), the operating speed is reached quickly and not an issue but if you set min Hz to say 400, it is noticeable...


----------



## rodw (Feb 27, 2015)

cwebs said:


> Hi RodW, I am still having trouble with speed control in V7, as I did in V5. I am running V4 and V5 with all "Speed set" commented out and speed set TIMER_DELAY =100 in place of 80 and my Nema 17 is happy there. Keep up the great work.
> 
> I also had to add the version number in the splash screen to keep track of witch version I am playing with. Had them all up at one time and got corn fused. Thanks, Carl



Carl, to convert TIMER_DELAY to Hz it works like this.
There are 1,000,000 microseconds per second. Thats how any times a second the timer interrupt is triggered.

But there are 2 pulses per stepper step (on and off) and a Herz measures cycles per second so the maximum frequency the Arduino can generate is 500,000 Hz (1,000,000/2)

So with a TIMER_DELAY of 100 you are running at 5,000 Hz (500,000/100)

You know your stepper will operate at 5,000 Hz so start by trying say Min Hz of 4000 and max Hz of 5000. if no good, try 5000 and 5500 or 4500 and 5500. Once you get it started, I'd reduce the min Hz until you get a reasonable ramp up period and then try increasing max Hz

Steppers have lower torque at lower speeds so the idea is to start slow to overcome inertia.


----------



## cwebs (Feb 27, 2015)

Hay Rod. In V7, I also noticed the when using Jog the stepper would keep going for some time and then go slowly a few more motor turns after button release befor stoping. I would think that in Jog mode it should stop when you release the button like in V4 and V5. 

In Speed Set, the speed didn't increase much when trying to go faster and would slow down about half after a few cycles. 

THe reason I needed to change the delay in speed set was because the stepper would "Lock up" when almost top speed was reached. By slowing it down to 100 from 80 the motor didn't stall or "Lock up". It would lock up at 95 but not at 100 so I went with 105 .  Carl


----------



## rodw (Feb 27, 2015)

I can see the home problem. At the very bottom of the code in the timerIsr ISR service routine, we are not maintaining the current direction anywhere as we are setting it directly throughout the code like this


```
digitalWrite( globals.DirPin, ANTICLOCKWISE );
```

We never really know which direction we are travelling. We should be reading the direction pin in the ISR so we can't get it wrong!

Here is the fix. At the very bottom of the code in the timerIsr ISR service routine (about 12 lines from the end of the file), where it says this:


```
steps--;
      if(!goinghome){
          if(globals.dir == CLOCKWISE){
             homePos++;
```

Change

```
if(globals.dir == CLOCKWISE){
```

To

```
if(digitalRead(globals.DirPin) == CLOCKWISE ){
```

we don't need to keep the direction in a variable as the hardware port does it for us!

Let me know if this fixes it.


----------



## rodw (Feb 28, 2015)

Finally got this back in the shed on my rotary table. The Home code above fixed half of the problem *Literally*! I ended up with 2 home positions each 180 degrees apart.

I went and mowed the lawn and it dawned on me that I must not have allowed for both sides (on and off) of a stepper pulse so I was only moving half a circle.

Anyway, I have fixed this now and added all of my eeprom features (load device, add device and select device. By my calculations the UNO has enough EEPROM storage to store up to 53 devices.



> Hay Rod. In V7, I also noticed the when using Jog the stepper would keep going for some time and then go slowly a few more motor turns after button release befor stoping. I would think that in Jog mode it should stop when you release the button like in V4 and V5.
> 
> In Speed Set, the speed didn't increase much when trying to go faster and would slow down about half after a few cycles.
> 
> THe reason I needed to change the delay in speed set was because the stepper would "Lock up" when almost top speed was reached. By slowing it down to 100 from 80 the motor didn't stall or "Lock up". It would lock up at 95 but not at 100 so I went with 105 . Carl




Carl, It sounds like you have not found the Setup menu that lets you change the speed settings and ports etc without changing any #defines in software code to configure the controller.

the reason why the system runs on is that the stepper winds down so the inertia of the table could push it on a step or 2. The default settings have too big a gap between the starting frequency and the maximum frequency so the ramp up and down takes too long.

Now that I've had more of a play, I found that a minimum frequency for my smallish NEMA 23 need to be around  5,000 Hz This will mean the ramp down is short and almost instantaneous.

So I have set my my Min stepper Hz to 5,000 and the Max Stepper Hz to 10,000 and it runs nice 60% faster than when I was just using a fixed timer frequency. Try those settings and see how you go. If you miss steps, alter the settings.

You will need to get your head around the frequency settings and forget totally about the timer delay setting as the next version will not have a Timer Delay setting at all.


----------



## rodw (Feb 28, 2015)

I thought I'd attach the document from Texas Instruments that explains how to correctly use a stepper motor and is what I based my ramp up/ ramp down code on. 

View attachment slyt482.pdf


----------



## rodw (Feb 28, 2015)

Version 8 is here!

Massive changes and this I think is the final feature set, memory is going to get very tight..

Hopefully all bugs are squashed.
The menu has changed a bit and all settings are now in the Config Menu so the main menu now contains:
 <Divide #>, <Divide Angle>, <Jog>, <Home>, <Contin Turn>, <Config>

The Config Menu contains:
<Set Speed>, <Jog Step>, <Setup>, <Devices>

<Set Speed> and <Jog Step> make temporary changes to the Jog Step and Max Stepper HZ which will be lost on reboot unless you go into setup and Save it.

Followers will be pleased to know the <Set Speed> menu has been reinstated.

<Devices> menu has 3 options
Load Device, New Device, Erase Devices

New Device and Erase Devices are Yes/No options

Erase clears the EEPROM (well changes the first 3 bytes so it thinks it is empty,

New Device makes a new device in memory and installs it.

Load Device allows you to select a device using up and down arrows. First device is numbered 0 (Thats how C works). There is enough memory for 53 devices but you'll have to remember which number is what.

Software version and current device are displayed on startup. 

View attachment RotaryTableChuck8.zip


----------



## rodw (Feb 28, 2015)

Version 8 now attached to the previous post


----------



## rodw (Feb 28, 2015)

Oops, 

The set speed code is wrong. Replace the *setSpeed()* procedure with this code:


```
void setSpeed(int spdPct)
{
  long newspeed;
  long mindelay =  HzToTimeDelay(Operating_Hz); 
  long maxdelay =  HzToTimeDelay(globals.minStepperHz);

  long DelayRangeHz = Operating_Hz-globals.minStepperHz;
  float changeRatio = (float)spdPct/100.0;
  long offset = (long)((float)DelayRangeHz * changeRatio);
  if(spdPct == 100)                          // Override the calculations ere so 100% is the max frequency
      newspeed = Operating_Hz; 
  else
      newspeed = globals.minStepperHz + offset;
  globals.timerDelay = HzToTimeDelay(newspeed);             // save globally
  globals.maxStepperHz = newspeed;

  Timer1.setPeriod(globals.timerDelay);      // set a timer of length in microseconds
}
```

I've reworked this to do the maths on the frequency instead of the timer delay. This has made it more accurate as well as I'm using much bigger numbers.

Just remember that the % is based on the speed range (between max Hz and Min Hz and this is then added to the Min Hz so it is not 90% of 10000 hz which you might expect on first glance. it is:
 (maxHz - MinHz) * 90% + MinHz

This means a speed of 0% is valid and will run at the lowest speed you have set in config for Min Hz.

You can check the speeds in the Setup


----------



## TorontoBuilder (Feb 28, 2015)

rodw said:


> Version 8 now attached to the previous post



Wow Rod, fantastic work! Thank you so very much. 

I hope that it's going to be easy enough for me to figure out how to modify for 4x20 IC2 display and to add code to display the stepper motor current on the 3rd or fourth line of the display


----------



## rodw (Feb 28, 2015)

TorontoBuilder said:


> Wow Rod, fantastic work! Thank you so very much.
> 
> I hope that it's going to be easy enough for me to figure out how to modify for 4x20 IC2 display and to add code to display the stepper motor current on the 3rd or fourth line of the display



I can't see it will be too much of a drama. Files to work with are LCD.h and LCD.cpp in the library and the LiquidCrystal files in the Utilities folder. 

LCD.cpp has this code

```
void LCD::init()
{
    // The Freetronics display is 16x2.
    begin(16, 2);
```
You just need to insert your version of the Liquidcrystal files. I think this page will guide you

https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home


----------



## cwebs (Feb 28, 2015)

Ok Rod, I now have my RT working with the nema 17. At this time I am still using V5 and had to make some tweaks. How ever it is running very smooth. I am getting 9 degs per second and that is faster then ChuckF's sketch would run. I am running nema 17 70 oz. three to one reduction with timing pulleys into a 90 turn 8 inch table. I had to tell the program that my stepper needed 600 steps per turn but that fell a few degrees short so I ended up using 640 steps per turn and after about 10 full revolutions it was spot on. I also had to slow the stepper down to pervert missed steps. I am running a DVR 8825 driver at just over one amp and only 12 volts from an ATX power supply. I know more voltage would run faster but I don't need any more speed. I will keep working on V8. How ever, I have played with these programs so much my buttons are starting to fail. LOL Might have to replace some of them. I need to find the correct diagram for the voltage divider so I can make a switch panel. Now to make the enclosure. Thanks again, Carl


----------



## rodw (Feb 28, 2015)

cwebs said:


> Ok Rod, I now have my RT working with the nema 17. At this time I am still using V5 and had to make some tweaks. How ever it is running very smooth. I am getting 9 degs per second and that is faster then ChuckF's sketch would run. I am running nema 17 70 oz. three to one reduction with timing pulleys into a 90 turn 8 inch table. I had to tell the program that my stepper needed 600 steps per turn but that fell a few degrees short so I ended up using 640 steps per turn and after about 10 full revolutions it was spot on. I also had to slow the stepper down to pervert missed steps. I am running a DVR 8825 driver at just over one amp and only 12 volts from an ATX power supply. I know more voltage would run faster but I don't need any more speed. I will keep working on V8. How ever, I have played with these programs so much my buttons are starting to fail. LOL Might have to replace some of them. I need to find the correct diagram for the voltage divider so I can make a switch panel. Now to make the enclosure. Thanks again, Carl



I know the feeling re fingers..and I had to buy a new lcd shield myself.

The circuit diagram for the keyboard is here http://www.freetronics.com.au/pages/16x2-lcd-shield-quickstart-guide

And of course, I found some bugs so here is V9. No new functionality, just cleaned up and a bit of a memory cleanup as I could not load devices in Version 8. Also the go home seemed to get confused on continuous turning if you chopped and changed direction. I think that was also related to lack of memory.

Try it. Just compile it as is and then go to <config> / <setup> and set the pins and parameters to suit you. There are 3 numbers to change the ratios
*M/Steps:* if you are microstepping
*Div ratio:* this will be 270:1 for you
*Stepr Steps/rev:* 1.8 degrees stepper is usually 200

Then set the min Hz to 5000 and max Hz to say 5500

Once you are happy, say Yes to *Save?*, reboot and check the settings are saved.

EDIT:For some reason, I can't edit Post #1 with thislink but version 10 is  here http://www.homemodelenginemachinist.com/showpost.php?p=263734&postcount=188 

View attachment RotaryTableChuck9.zip


----------



## rodw (Feb 28, 2015)

rodw said:


> Try it. Just compile it as is and then go to <config> / <setup> and set the pins and parameters to suit you. There are 3 numbers to change the ratios
> *M/Steps:* if you are microstepping
> *Div ratio:* this will be 270:1 for you
> *Stepr Steps/rev:* 1.8 degrees stepper is usually 200
> ...



Carl on second thoughts for you, I think you need to set the 
*M/Steps:*  = 1  - no microstepping
*Div ratio:* = 90
*Stepr Steps/rev:* = 640


----------



## cwebs (Mar 1, 2015)

rodw said:


> Carl on second thoughts for you, I think you need to set the
> *M/Steps:* = 1 - no microstepping
> *Div ratio:* = 90
> *Stepr Steps/rev:* = 640


Rod, I am trying V9 and have it MOSTLY working but I still have a problem with speed control. Some kind of bug? I have divisions set to 4 and watch turn table move 90 degs. No problem Always turns 90 degs. Ramp up is for the first 3 degs of turn and ramp down is the last 3 degs. No problem. But, the top speed is fast for the first three movements. 3 times 90 degs, about 10 degs per second, then the speed halves for all future moves to about 5 degs per seconds. Reboot and speed set made no different. Three times full speed then drops to about half. I had similar speed problems in earlier versions. What's up with that? Carl

PS Yes I am saving setting by using yes in save settings.


----------



## rodw (Mar 1, 2015)

cwebs said:


> Rod, I am trying V9 and have it MOSTLY working but I still have a problem with speed control. Some kind of bug? I have divisions set to 4 and watch turn table move 90 degs. No problem Always turns 90 degs. Ramp up is for the first 3 degs of turn and ramp down is the last 3 degs. No problem. But, the top speed is fast for the first three movements. 3 times 90 degs, about 10 degs per second, then the speed halves for all future moves to about 5 degs per seconds. Reboot and speed set made no different. Three times full speed then drops to about half. I had similar speed problems in earlier versions. What's up with that? Carl
> 
> PS Yes I am saving setting by using yes in save settings.



Carl,  cool you have got it mostly working. After division 4 go into setup and see if Max Hz has changed. Then reboot and see what it is.

I'll try and replicate it. It is possible we are running out of memory. I found the latest version of the IDE cut smaller code.

Either that or the marker to set the end of ramp up and start of rampdown is notgetting set correctly.


----------



## rodw (Mar 1, 2015)

rodw said:


> Carl,  cool you have got it mostly working. After division 4 go into setup and see if Max Hz has changed. Then reboot and see what it is.
> 
> I'll try and replicate it. It is possible we are running out of memory. I found the latest version of the IDE cut smaller code.
> 
> Either that or the marker to set the end of ramp up and start of rampdown is not getting set correctly.



Carl, I just went out and did  well over 20 x 90 degree divisions with a digital tacho on the stepper shaft and the speed was constant at 300 rpm. I think your problems will be memory related as I had problems with continuous turning which went away when I shortened some of the prompts.. Have a look at the first post where I talk about this and then see what your results are and post up your compiler message. I'll  check mine and we can compare.


----------



## rodw (Mar 1, 2015)

Here's what I mean.

```
Sketch uses 24,412 bytes (75%) of program storage space. Maximum is 32,256 bytes.
Global variables use 900 bytes (43%) of dynamic memory, leaving 1,148 bytes for local variables. Maximum is 2,048 bytes.
```


This is the critical part

```
leaving 1,148 bytes for local variables.
```

If when running this memory runs out crazy things start happening.

If your number is smaller, chances are this is the problem

Try commenting out the setup routine with a /* and */ immediately after the first brace and immediately before the last brace like this.


```
void doSetupMenu(void)
{
/*  
  Form setupForm(lcd);
  int saveSetup = false;
.
.
.
  if(saveSetup){
    int retval = putGlobals();
  }
*/
}
```

This will save a lot of memory (100 bytes for me). 

```
leaving 1,246 bytes for local variables.
```
If it works then we know its memory related.


----------



## rodw (Mar 2, 2015)

I've been thinking about Carl's problem which I'm sure is related to memory overflows from a memory leak. Typically, leaks manifest when scode is called repeatedly. If this is the case it has to be in the external classes I'm using for forms and fields. I find the best way to solve problems is to leave them alone for a while to let the brain work its way though it.

I'm wondering if forms are not clearing themselves correctly when exiting a procedure. In the examples, all forms and fields were global variables and I moved them to procedures to free up memory. The *printDivideVals* is called every time you do a division so it is a very busy piece of code. It contains a form that is never used but I added it to format an angle. I'm wondering if the Field is not being erased correctly in exit.

I had some problems when testing 20 odd divisions this morning as afterwards I could not enter the Home menu so maybe this was enough for me to see the memory leak manifest itself on my system.


Carl, I'm wondering if you add this to the end of the procedure

```
tempForm.removeField(&tempField);
```

as shown here.

```
void printDivideVals(int iDiv,long iAngle)
{
  Form tempForm(lcd);
  DegreeField tempField(tempForm, "", 360, DEGREEFIELD_READ_WRITE); // Just using this to convert to degrees

  lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Div: ");
   lcd.print(iDiv);
   lcd.print(" of ");
   lcd.print(divisions);
   tempField.setValue(iAngle);
   tempField.printDegrees();
   lcd.setCursor(10,1);
   lcd.print(" / Div"); 
  tempForm.removeField(&tempField); 
}
```

In theory, the compiler should look after all of this for us but its worth a try. If this solves your problem, I know to go through all of the other procedures and explicitly remove all fields on exit in this way..

Please report back...


----------



## cwebs (Mar 2, 2015)

rodw said:


> I've been thinking about Carl's problem which I'm sure is related to memory overflows from a memory leak. Typically, leaks manifest when scode is called repeatedly. If this is the case it has to be in the external classes I'm using for forms and fields. I find the best way to solve problems is to leave them alone for a while to let the brain work its way though it.
> 
> I'm wondering if forms are not clearing themselves correctly when exiting a procedure. In the examples, all forms and fields were global variables and I moved them to procedures to free up memory. The *printDivideVals* is called every time you do a division so it is a very busy piece of code. It contains a form that is never used but I added it to format an angle. I'm wondering if the Field is not being erased correctly in exit.
> 
> ...


Ok, here go's Rod...I compiled V9 and the report was. Binary sketich size 26576 bytes (of a 30720 byte maximum).
Ran it defalt with Divisions set to 4 (90 degs) hit go button and stepper starts then stalls. Config/Set speed = 100%. Reduced that to 50%. Speed was fine BUT, it turned 140 degs.

Config/Setup shows Max Hz at 1290 and Min Hz at 1000. Steps per Rv at 640. Half stepping set to 2 on both skitch and driver.

Reset every thing in Setup the same as above and this time it turned 90 degs as it should. Pushed go button again and speed was half first 90 deg turn. WTH?

Inserted tempForm.removeField(&tempField); and recompiled. Set Divisions to 4 again and hit go button. Turned at half speed.

Back to Config/Setup. Speed was at 100%, Max Hz still 1290, Min Hz still 1000, Steps per Rv 640. Back to Divisions set to 4 still. Hit go button and table turned 100 degs. 

I had a full head of hair, but, now I'm down to two big bald spots on the sides and a strip of hair down the middle.

Reset every thing and set divisions to 4 and hit go button again. This time it turned 230 Degs and half speed.

I have V5 working great with Speed Set commeted out. Now my fingers are bleeding and my head hutz. Carl


----------



## rodw (Mar 2, 2015)

Carl,

You better add memory loss to your  list of problems beside hair loss and bleeding fingers 
My Arduino UNO has 2k more memory than yours.....
V5 has 489 lines of code
V9 has 972 lines of code
No wonder you are loosing your hair!

I guess though if you have a working solution, its not worth loosing much sleep over.

Whenever I've had strange things happening it's righted itself when I've reduced memory use freeing up more memory for local variables.  Its not actually total memory used that is the problem, its whats left for local variables that is the limiting factor. You did not say how much you had left. There is only 2k of this to go round. Sounds like you have an earlier boot loader in your Arduino and probably an earlier version of the IDE which are stealing memory. (I'm on IDE V 1.6.0 and upgrading to it, gave me more memory.)

Yesterday, I set it up with 144 divisions and ran hundreds and hundreds of steps without rebooting and no problems with the software at all. BUT...

My little 60 oz NEMA23, I'm missing steps no matter what I do with the speed control. I have been using a 3.5 amp x 19 volt power supply. I've ordered a 7.5A x 48V power supply and a 266 Oz stepper. The power supply alone may fix it as it. According to Gecko, that alone should give me 2.5 x more torque but while I was paying postage, I added the stepper to the order as it was only $40, $30 cheaper than the power supply.

When I look at most 6" Rotary table with steppers mounted up, the stepper bodies are 76mm (3") long and mine is only 42mm long. hence my underpowered stepping problem. You don't notice it with a small number of divisions but after 144, it shows up as 1-5 degrees and I hear it miss steps.

Anyway, I'll report back once I've fixed the hardware but I'm giving V9 a clean bill of health for now.


----------



## cwebs (Mar 2, 2015)

rodw said:


> Carl,
> 
> You better add memory loss to your list of problems beside hair loss and bleeding fingers
> My Arduino UNO has 2k more memory than yours.....
> ...


 I am also running 1.6.0 and the Adaboot, bootloader. I am very happy with running my set up on V5. Carl


----------



## cwebs (Mar 5, 2015)

Rod, I have my controller all built using a perf board, bare bones with 1602 display and a button shield that I got from Your Duino. http://yourduino.com/sunshop2/index.php?l=product_detail&p=334

Every thing is working great but, I have one problem left. My "Up and Down" buttons are backwards. I don't know where to change the settings for these buttons. The only place I have found that makes reference to the buttons is in the LCD library under, 

// Button event codes.
#define LCD_BUTTON_NONE 0
#define LCD_BUTTON_LEFT 1
#define LCD_BUTTON_RIGHT 2
#define LCD_BUTTON_UP 3
#define LCD_BUTTON_DOWN 4
#define LCD_BUTTON_SELECT 5
#define LCD_BUTTON_LEFT_RELEASED -1
#define LCD_BUTTON_RIGHT_RELEASED -2
#define LCD_BUTTON_UP_RELEASED -3
#define LCD_BUTTON_DOWN_RELEASED -4
#define LCD_BUTTON_SELECT_RELEASED -5
#define LCD_LONG_SELECT -6

Will moving Up to Down and Down to Up, work? Or, simply change the numbers 3 and 4? Or am I in the wrong place?? Carl


----------



## rodw (Mar 5, 2015)

Carl, great you have got it going.
I think if you change the 2 equates it will fix it.
eg 
#define LCD_BUTTON_UP 4

If not, you will need to build a new keymap which i discussed in this thread earlier


----------



## cwebs (Mar 5, 2015)

rodw said:


> Carl, great you have got it going.
> I think if you change the 2 equates it will fix it.
> eg
> #define LCD_BUTTON_UP 4
> ...


 

That didn't work. I am done and everything is working great so I will leave it alone. 
 I just started using Eagle with pcb to gcode and my first lession is to make a board for the Rotary Table/Dividing head. Did get some of it done and it looks like it will work. Much more to add and cut a board to test. Maybe more news on that later.  Thanks for your work. Carl


----------



## rodw (Mar 5, 2015)

Carl,

In front of a PC now so I could have a look at your stuff properly. Sometimes a tablet does not cut it!
I think what you could do is invert the board  which will fix the up and down buttons and swap the default direction around on line 45 of version 5


```
int dir = CLOCKWISE;  // Carl, make this ANTICLOCKWISE
```

It sounds like you have got quite a bad bug with all this electronics!

My stepper and 48 volt power supply turned up and the extra volts fixed my missing steps so I have a spare stepper.

I made a start on version 10 last night that adds a device type that allows you to choose from a rotary device for rotary tables or a linear device for non-CNC mill table feeds etc. 

I'm not sure If I will squeeze it all into memory without hacking the LCD class to use PROGMEM strings, but I have the menus all configured and changing according to the device type, just have to sort out distance input and how to move a given distance.That won't be hard. 

This would let you use the controller and a stepper for a power feed and then change devices and plug it into a rotary table.

I have a software developer friend who is a woodworker who would love to have precise control of his back gauge on his table saw which is another linear application....


----------



## cwebs (Mar 6, 2015)

rodw said:


> Carl,
> 
> In front of a PC now so I could have a look at your stuff properly. Sometimes a tablet does not cut it!
> I think what you could do is invert the board which will fix the up and down buttons and swap the default direction around on line 45 of version 5
> ...


 
That change didn't work either. It made "Home" go wrong way. I started at 0 degs set divisions to 4. Turned to 90 degs and then tried to home and it turns to 180 degs.

AS to the power feed, I think that would be a great idea. I was going to make something for my Mill to do just that. But as you said, I can't remember that much. Must be my age. I think. Carl


----------



## rodw (Mar 6, 2015)

cwebs said:


> That change didn't work either. It made "Home" go wrong way. I started at 0 degs set divisions to 4. Turned to 90 degs and then tried to home and it turns to 180 degs.
> 
> AS to the power feed, I think that would be a great idea. I was going to make something for my Mill to do just that. But as you said, I can't remember that much. Must be my age. I think. Carl



The homing code is in the ISR. 


```
if(!goinghome){
        if(dir == CLOCKWISE){
          homePos++;
          if(homePos > (long)STEPS_PER_REV)
            homePos = 0L;      
        } 
        else{
          homePos--;
          if(homePos < 0L)   
            homePos =  (long)STEPS_PER_REV;
        }
    }
```

I think on reflection,  I told you the wrong thing yesterday. We probably should have changed these around. 

```
#define CLOCKWISE     LOW
#define ANTICLOCKWISE HIGH
```

I guess thats why I made these #defines in the first place. So you did not have to change any code to suit the hardware!

Don't hold your breath for the linear features.


----------



## rodw (Mar 9, 2015)

Well I finally got around to using the controller for a continuous milling job. A couple of years ago, a forum member gave me an angel eye light to go round the mill spindle.







But it has exposed soldered lugs on the back of the board that could short out.






So it needs a rebate so it won't short out on the mounting plate.

I made this up on the weekend. 






I used the 4 jaw chuck to bore the hole for the spindle in the centre and offset it by 5mm before cutting the groove. I did thios to make room for the clamping bolt. I could not cut the rebate to gain the clearance I needed with the lathe tooling I had so I set it up on the rotary table. Don't ask me how long it took to centre the job on the lopsided hole. A 4mm end mill did the trick nicely to widen the hole on the outside that I could not get to on the lathe.






And here's the finished article





and where it will go






As an added bonus, I'm going to machine a flat on the side so I can mount up a depth gauge for the mill.






Now if only my 25 year old TC201 Weller Soldering Iron hadn't have decided to die during the week now I'm almost ready to solder up a control board.....


----------



## rodw (Mar 10, 2015)

And here was I thinking I'd glue the light in with silicone but then realised it would be much easier to service if I secured the light with screws. So I set the mounting plate up on the rotary table again and set it for 3 divisions and added some M3 flanged screws out of my PC spares drawer.






THe rear screw is mounted on the inside as the power lead exits on the outside.





Way off topic I know, but this light is just awesome!






Absolutely no shadows anywhere. The 120 mm angel eyes lights are about $7.50 a pair on ebay ex China so I will have spares available.


----------



## Wizard69 (Mar 12, 2015)

It isn't off topic and frankly the older I get the more important good lighting is.   The real question is where does one buy such ring lights.


----------



## TorontoBuilder (Mar 12, 2015)

Wizard69 said:


> It isn't off topic and frankly the older I get the more important good lighting is.   The real question is where does one buy such ring lights.



Ebay or amazon


----------



## Holt (Mar 13, 2015)

Wizard69 said:


> It isn't off topic and frankly the older I get the more important good lighting is. The real question is where does one buy such ring lights.


 
http://www.aliexpress.com/premium/a...=y&origin=y&initiative_id=&isViewCP=y&catId=0

Here they are in all sizes.


Holt


----------



## rodw (Mar 13, 2015)

Wizard69 said:


> It isn't off topic and frankly the older I get the more important good lighting is.   The real question is where does one buy such ring lights.



Another forum member gave me one that he bought off eBay (becasue they came in a pair) and I gave him an aluminium offcut to mount his on in return. Pretty sure this is what he bought. Well, the dimensions are the same.

http://www.ebay.com.au/itm/1Pair-12...40?pt=LH_DefaultDomain_15&hash=item51b1091138


----------



## rodw (Mar 13, 2015)

I finally got a bit of time tonight to play with some code again. Pretty sure I've got the LCD class extended to type in a number to 3 decimal places. eg 9.999.

I figured the number could represent millimetres (to 0.001) or inches (to 1 thou or 0.001")
This is an important step for a linear device so you can enter the distance per revolution so it needed to be done before I could add this functonality. I'm actually cheating a bit because while the display shows decimal numbers internally, the number is a long representing the smallest unit of measurement (microns in metric or thou in imperial). eg 0.001 is actually 1 in the code. It would not be too hard to add an extra decimal place. If you imperial guys thought it was necessary, let me know in this thread.

Quite excited to see TorontoBuilder has got his controller boards back.


----------



## chucketn (Mar 13, 2015)

Can't wait, Rod. The biggest drawback to Chuck F's original configuration is that I can't enter # of divisions directly. I have successfully cut a set of 46 tooth change gears with my setup of Chuck F's version, but experienced difficulties when cutting a pair of 64 tooth gears. My Sainsmart LCD-Keypad shield started having button issues. Entering the # of divisions, and stepping for the next cut had numerous button errors or failed responses. At one point, the Arduino actually changed # of divisions spontaneously, and I ended up messing up the 64 tooth gears, on the last cut, of course.
Part of the problem may have been the 9v battery I was using to power the Arduino, it died enough that the display was not readable for the last few cuts. I think the wear and tear on the buttons entering the # of div by repeatedly pressing a button will make for a short life for the shield. I don't know if contact cleaner will help the button issue. I plan to reload the Arduino and try a single 52 or 54tooth gear today.

Chuck
I do have a 5 button module coming on the slow boat...


----------



## chucketn (Mar 13, 2015)

Rod, are you adding a matrix keypad to this project?

Chuck


----------



## rodw (Mar 13, 2015)

chucketn said:


> Can't wait, Rod. The biggest drawback to Chuck F's original configuration is that I can't enter # of divisions directly. I have successfully cut a set of 46 tooth change gears with my setup of Chuck F's version, but experienced difficulties when cutting a pair of 64 tooth gears. My Sainsmart LCD-Keypad shield started having button issues. Entering the # of divisions, and stepping for the next cut had numerous button errors or failed responses. At one point, the Arduino actually changed # of divisions spontaneously, and I ended up messing up the 64 tooth gears, on the last cut, of course.
> Part of the problem may have been the 9v battery I was using to power the Arduino, it died enough that the display was not readable for the last few cuts. I think the wear and tear on the buttons entering the # of div by repeatedly pressing a button will make for a short life for the shield. I don't know if contact cleaner will help the button issue. I plan to reload the Arduino and try a single 52 or 54tooth gear today.
> 
> Chuck
> I do have a 5 button module coming on the slow boat...




Chuck, try and use a 12 volt plugpack supply for your Arduino. Its possible that it can't provide enough current to drive the LCD, keyboard and stepper. I don't know if others have used your stepper driver, it may use more power. I also replied on your other thread.



chucketn said:


> Rod, are you adding a matrix keypad to this project?
> 
> Chuck



No. Have to leave something for you guys to do! Someone else thought a rotary encoder would be good to use so where does it stop?

I've bought 5 bigger buttons (1 red for select and 4 black ones) and a hand full of resistors and was going to hardwire it into a case and rebuild to the Freetronics keyboard circuit diagram. I thought that would be more robust in a shop environment.

I'm holding off on putting it in the case. I've got a 48 v power supply to drive my stepper and have a couple of step down power supplies coming on the slow boat (10 amp 48-12v for arduino and spindle light and 5 amp 48-24v for an electric clutch on my X axis power feed.) The idea is that turning off the clutch will completely disengage the power feed to revert to the mill's hand control. The power supply is pretty big so I think I'll mount it on the mill somewhere and maybe have a smaller LCD display and button box. 

I decided to get the spindle light fitted up so it could be part of the project.


----------



## rodw (Mar 14, 2015)

Hmm, I think I'm going to be able to squeeze this all in... Just! I keep making the text prompts shorter to do it though. 

I was never sure I would make it!

So I have got all of the framework done and just have to convert a distance into the number of steps and the one Arduino will be able to control rotary and linear devices and swap between them at will. In fact thinking about it, because the step and direction ports are stored in EEPROM for each device, you could add more than one stepper controller.


----------



## Scott_M (Mar 16, 2015)

Hi Rod

Sorry I have been absent. Just finished a big job and have been out of town with delivery and installation. 

Your " Rotary Table Controller" has grown to be  quite a monster , doing much more than originally planned. Funny how projects grow , isn't it ?
I too will be ordering a 48 V supply and trying to get this wrapped up.

Question, I will want to add an external switch to control "Next" or a right button press. We will be adding a proximity switch so my buddies old 3 axis mill can move over to the prox switch and advance the rotary table to the next position.
Should I try to set it up as "that button" or add another on an open analog input calling the same function ?

Thoughts ?


Scott


----------



## rodw (Mar 17, 2015)

Scott_M said:


> Hi Rod
> 
> Sorry I have been absent. Just finished a big job and have been out of town with delivery and installation.
> 
> ...


Scott glad you are back, I wondered where you got to. Yes, I'll get the monster done! I'm not coming at this from a CNC background but I think what you want to add another switch that functions as the right button. 

I've thought about this in terms of adding a rotary encoder to enter data. If you only want one button recognised, I think I'd use a digital port for the new switch.

Throughout the sketch you will see a loop with code like this:

```
event = lcd.getButton();
      switch(event){
        case LCD_BUTTON_RIGHT:
...
```

I'd either edit the  lcd.getButton() function in the LCD class  to test our new port and return LCD_BUTTON_RIGHT if it sensed your button was pressed.

Alternatively, if its only one procedure you want this to work in, maybe you could modify the piece of code above to look for the extra input. Something like this:


```
event = lcd.getButton();
      if(myButtonIsPressed())
         event = LCD_BUTTON_RIGHT;
      switch(event){
        case LCD_BUTTON_RIGHT:
...
```

Just remember your input must be 5 volts max and to debounce the button.

So as a progress update, I got the linear version in the shed last night and gave it a run. I have a few bugs.


table direction appears reversed and can't be fixed in the config menu
Linear home goes the wrong way. (Probably because of above)
Rotary Home broken
Can't test the distance is correct until I fit a power feed stepper but did check the steps were being calculated correctly.

The home functionality is a bit complex because in rotary mode, it needs to be reset when it passes the 0 degree mark but this is not the case in the linear mode.... and it involves the low level ISR routine.

Nothing I can't sort out when I get a bit of time. TorontoBuilder has been reviewing his hardware design so it will support multiple steppers. Check his thread too.


----------



## Scott_M (Mar 17, 2015)

Hi Rod

Thanks !

```
event = lcd.getButton();
      if(myButtonIsPressed())
         event = LCD_BUTTON_RIGHT;
      switch(event){
        case LCD_BUTTON_RIGHT:
...
```
 
I think this will do nicely, I will give it a try.

Scott


----------



## rodw (Mar 18, 2015)

rodw said:


> So as a progress update, I got the linear version in the shed last night and gave it a run. I have a few bugs.
> 
> 
> table direction appears reversed and can't be fixed in the config menu
> ...




Well, I solved a couple of issues so just have this one to go.

table direction appears reversed and can't be fixed in the config menu

I've got a bit of rework to do here as I don't think my direction code was ever written properly. Ideally, we just need to be able to go into the device setup and "swap direction". eg, if it is going the wrong way, make it swap the direction and forget about clockwise and anticlockwise as if using a linear device, it is meaningless. Still need to think it through.


----------



## Scott_M (Mar 18, 2015)

Hi Rod

Could you make the "Swap"  swap button assignments ?  Like ,  left becomes right and right becomes left ?

Scott


----------



## rodw (Mar 18, 2015)

Scott_M said:


> Hi Rod
> 
> Could you make the "Swap"  swap button assignments ?  Like ,  left becomes right and right becomes left ?
> 
> Scott


Thats what I had in mind. Its currently able to be changed by swapping the #defines for CLOCKWISE and ANTICLOCKWISE So I have to do that without hard coding. Its not hard, I just needed to think out the best way that links the swapping to the globals.dir field.


----------



## rodw (Mar 19, 2015)

Well, Here is version 10 which has almost 1000 lines of code more than V1. I have one problem though and it comes from not putting my electronics in a safe enclosure. I shorted out my Gecko stepper controller and it looks like it has been fried so I could not give this a final test. I tested against an earlier known good verson and the stepper does not operate. :fan:

Therefore, it may be a while before I make much more progress but maybe you guys can test this for me in the mean time.

New features are:
_*New device type to a linear drive.*_
Note there is a new ratio for this controller type. In my case my drive cogs are going to be 32 teeth and 25 teeth so I can enter a ratio of 1.28 to suit.

*Swap direction in Setup menu*
This is the bit I did not get to test. Go to <Config><Setup> and there is a prompt that says "SwapD" (eg Swap Direction) that asks for a yes or no answer. If you answer "yes" the direction of travel when pressing the left and right buttons should change. to make permanent, make sure you save the setup. If you find problems, please explain issue clearly and I'll try and fix it.

*New really cryptic menu options*
Sorry about this guys but I was really pushed for RAM because the LCD class uses the String type for all of the prompts. If anybody wants to make a really valuable contribution, edit the Form and field classes in the LCD library  library to eliminate use of the String type and use PROGMEM variables instead. Don't bother working with this script when you do that, just get the example form.ino sketch working with PROGMEM variables. and I' can fold it into this sketch.

I'm pretty sure it will all work as expected. I took my time and had it error free before I worked on the change direction code. If you search for CLOCKWISE and ANTICLOCKWISE, you will see the changes I made to enable this. If it isn't working, I can post up the prior version as V 9.5. and you can try that. 

View attachment RotaryTableChuck10.zip


----------



## Scott_M (Mar 19, 2015)

Hi Rod
I tried to compile V 10 and got an error.
It appears that I do not have the  GetMicroField.h library and under that in the include list is another new library avr/pgmspace.h  That was not there before. I do not know if this one will throw an error as well.
I goggled around and could not find either. 

Scott


----------



## rodw (Mar 19, 2015)

Scott_M said:


> Hi Rod
> I tried to compile V 10 and got an error.
> It appears that I do not have the  GetMicroField.h library and under that in the include list is another new library avr/pgmspace.h  That was not there before. I do not know if this one will throw an error as well.
> I goggled around and could not find either.
> ...



Ooops, sorry about that!. Here is an updated LCD library with the missing field type. Basically, this is a number in microns that specifies the distance to move in a linear environment. eg in units of 0.001mm.  But when entering data, it puts a decimal point in.

You can comment out or delete

```
#include <avr/pgmspace.h>
```
That is when I was trying to implement PROGMEM strings but I gave up.
This header file should be buried in the Arduino environment as its part of the underlying Atmel AVR environment that the Arduino is built on. 

View attachment LCD (2).zip


----------



## Scott_M (Mar 19, 2015)

Thanks Rod !
That did it. Compiled fine and I played with it a little bit. It all seems to work. I will give it a more in depth review tomorrow.

Scott


----------



## rodw (Mar 20, 2015)

Scott_M said:


> Thanks Rod !
> That did it. Compiled fine and I played with it a little bit. It all seems to work. I will give it a more in depth review tomorrow.
> 
> Scott



Awesome! I am not very happy sitting here on the sidelines 

Post up the bugs If you find any. Pretty sure it all works. I just wanted to  check the swap direction feature worked.


----------



## Scott_M (Mar 20, 2015)

Hi Rod
I was just playing with it hooked up to my 40 turn dividing head.
Everything works !  Swap works just fine. Home works as well. I messed with it for about an hour and only had one strange thing happen that I could not reproduce.
One time after the screensaver came on, I could not wake it. The screen showed all kinds of weird characters just random segments of all of the top row of characters. I had to unplug it to get it to reset.

That happened early and only once. Not sure what it was all about but , it has not reappeared.

Otherwise......AWESOME !!

I am going to see if I can get my external proximity switch working as a button today.

Again, many thanks for all your hard work.


Scott


----------



## Scott_M (Mar 20, 2015)

Well I guess I'm not as clever as I thought had hoped. 
I first tested my switch with the onboard LED and a basic button sketch. It works on the input selected. I am using D12, I think that is free ?

I first defined my switch and pins here

```
const int proxPin = 12;      // the number of the proximity switch pin
int proxState = HIGH;             // the current reading from the input pin
int lastproxState = LOW;   // the previous reading from the input pin
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time
 
void setup() 
{
   pinMode(proxPin, INPUT);
 
   const char welcome1[] PROGMEM = "VMN Ctrl";
   const char welcome2[] PROGMEM = "V:";
   const char welcome3[] PROGMEM = "D=";
```
 
And only added the call code to the 2 events I am concerned about, which are Divide # and Divide angle . I added this to both of those fields right after the "getButton" call

I added this


```
proxState = digitalRead(proxPin);
            if(proxState=LOW)
         event = LCD_BUTTON_RIGHT;
```
 

Like this


```
void goDivide(long gAngle)
{
   long thisDiv = 1; 
   int event = LCD_BUTTON_NONE;
   float tmpSTEPS_PER_REV = (float)globals.stepsPerRev;
 
   stepsPerDiv = (long)(tmpSTEPS_PER_REV *((float)gAngle/(float)MINUTES_IN_CIRCLE));
   divisions = (long)((float) MINUTES_IN_CIRCLE / (float) gAngle);
   printDivideVals(thisDiv,gAngle);
   while(event != LCD_BUTTON_SELECT){
      event = lcd.getButton();
      proxState = digitalRead(proxPin);
            if(proxState=LOW)
         event = LCD_BUTTON_RIGHT;
      switch(event){
        case LCD_BUTTON_LEFT:
          thisDiv--;
          if(thisDiv < 1)
            thisDiv = divisions;          
          digitalWrite( globals.DirPin, ANTICLOCKWISE );
          setSteps(stepsPerDiv * 2, 1);
          printDivideVals(thisDiv,gAngle);
          break;
        case LCD_BUTTON_RIGHT:
          thisDiv++;
          if(thisDiv > divisions)
            thisDiv = 1;          
          digitalWrite( globals.DirPin, CLOCKWISE );
          setSteps(stepsPerDiv * 2,1); 
          printDivideVals(thisDiv, gAngle);
          break;
```
 
I am also pretty sure I don't have the debounce code right either.

Any help that you code wizards may have would be appreciated 

Many Thanks


Scott


----------



## rodw (Mar 20, 2015)

Scott,

Great feedback thanks

I think you've made a simple mistake here

```
if(proxState=LOW)
```

C needs 2 equal signs when testing for equality so it should be

```
if(proxState==LOW)
```

If you have trouble with debouncing, try this http://playground.arduino.cc/Code/Bounce
but there are some other simple examples on the Arduino site


----------



## Scott_M (Mar 20, 2015)

Damn Rod....Your good, you fixed it from half way around the world!!!!!


I still had it powered up on the bench, and that indeed fixed it.

Thanks again.

Scott


----------



## rodw (Mar 20, 2015)

Scott_M said:


> Hi Rod
> I was just playing with it hooked up to my 40 turn dividing head.
> Everything works !  Swap works just fine. Home works as well. I messed with it for about an hour and only had one strange thing happen that I could not reproduce.
> One time after the screensaver came on, I could not wake it. The screen showed all kinds of weird characters just random segments of all of the top row of characters. I had to unplug it to get it to reset.
> ...


FANTASTIC!

It sounds like it could have been a loose connection or something.  Other than that, it could be a memory leak in the LCD class somewhere which is not my code. I did put some explicit remove field statements in the main functions to try and stop this because at one stage on long sessions I had some similar problems very early on. You'll see this at the end of 
the enterDivisions function as an example.

Oh and be disciplined with indenting your code. It makes it so much easier to debug when something goes wrong. eg

```
proxState = digitalRead(proxPin);
   if(proxState==LOW)
       event = LCD_BUTTON_RIGHT;
```


----------



## rodw (Mar 21, 2015)

Scott_M said:


> Damn Rod....Your good, you fixed it from half way around the world!!!!!
> 
> 
> I still had it powered up on the bench, and that indeed fixed it.
> ...



Scott, I must have cross posted this morning and missed this. Have you any idea how many times I've been caught since I taught myself C back in 1990?

It is rare I get caught anymore, but I did do the same thing once in this project.


----------



## cwebs (Mar 23, 2015)

Hi Rod. I read you lost your driver, well, I did the same thing. Now I am looking for some one to blame. Like you I can't leave well enough alone. Rebuilt my old controller and had every thing working great, but, I run it on only 12 volts and tried it with 24 volts. BIG cloud of smoke and the 4988 driver was fried. It should have worked fine on only 24 volts but smoked anyway. Then I had 5 8825 drivers show up in the mail only minutes later. Stuck in new 8825 and pow, another cloud of smoke. All I could do is laugh. Couldn't find the short so I took the wire cutters to every thing. Then I loaded up Eagle Cad and milled out a new board. Didn't like the first one so went back and Eagle cam,ed a new board. It's all back together and working fine. I have to put it away before I do more to it. Now I have to figure out who to blame. Any ideas? Carl


----------



## rodw (Mar 23, 2015)

cwebs said:


> Hi Rod. I read you lost your driver, well, I did the same thing. Now I am looking for some one to blame. Like you I can't leave well enough alone. Rebuilt my old controller and had every thing working great, but, I run it on only 12 volts and tried it with 24 volts. BIG cloud of smoke and the 4988 driver was fried. It should have worked fine on only 24 volts but smoked anyway. Then I had 5 8825 drivers show up in the mail only minutes later. Stuck in new 8825 and pow, another cloud of smoke. All I could do is laugh. Couldn't find the short so I took the wire cutters to every thing. Then I loaded up Eagle Cad and milled out a new board. Didn't like the first one so went back and Eagle cam,ed a new board. It's all back together and working fine. I have to put it away before I do more to it. Now I have to figure out who to blame. Any ideas? Carl



I wondered why you were so quiet. I know the feeling. But I bought a 48 volt power supply so I can't really pull out my little Pololu. I've been sitting back thinking about the next step.

Clearly a hardware issue, definitely not a software problem so don't blame me!


----------



## Scott_M (Apr 30, 2015)

Hey Rod, having some issues with accell and decell. Am trying to figure out how you are handling this. Is it just a ratio between min and max hz ?

I currently have my max set at 12500 and min at 7000.
Should I lower the min to get longer accell and decell or do I need to add steps to the "ramp up" and "ramp down" definition ?

Scott

Edit: Just changed min to 4000 and it seems to be working much better.

I will have a full report on this project in a few days. It came out reeeealllllly nice !


----------



## rodw (May 2, 2015)

Scott, sorry for being a bit slow. I have not got back to this project. My foray into steppers got me in and I've been designing a CNC plasma cutter...

I found it needed a bit of trial and error. Setting the start speed too low did not seem to be a good idea. The ramp up worked but it was really slow getting going...

Basically, it starts out by working out how many steps (call it X) it needs to do to get from 7000 to 12500 and changes the frequency every time it does a step. Once it gets to 12500 it stays at that speed until It gets X steps away from the finishing position and the slows the frequency down each pulse until it gets back to 7000 on the very last step of the movement.

If the distance is short, and it can't get up to 12500 and back down again, maybe it only has enough room to get to 9000 and back to 7500 again, it will never reach the max speed of 12500.

I did link to a pdf file from TI that explains this. Worst case set the start and end speed to be the same.


----------



## Scott_M (May 2, 2015)

Thanks Rod

It seems like if the spread between min and max is large it is an issue. I think I may lower Max just so I can lower Min some more.
This is a 40:1 Dividing head so it turns plenty fast. It is a like new 50's vintage "Cincinnati" It is HUGE ! My buddy is putting an 8" 3 jaw on it.
I will post a build log on it next week when I get down to my buddy's and get some video of it. Here is a pic of the top of the Arduino box.

I can't thank you enough for all you did on this project !! My project has turned out really well because of it.

Scott


----------



## rodw (May 2, 2015)

Scott, that looks great. Keep the pics coming.I'm really pleased to see someone run with my contoller hardware.

From talking to a mate, even MACH3 requires some experimentation with ramp up and ramp down parameters. And yes, I found much the same thing with the settings. I would keep the start speed as high as I could for reliable starting without loosing steps.


----------



## Cogsy (May 2, 2015)

rodw said:


> I've been designing a CNC plasma cutter...


 
I was in on the design and build of a largish CNC plasma cutter a couple of years ago. The one piece of advice I can give is that you really need a good automatic torch height controller. 

You probably already knew but just in case you didn't...


----------



## rodw (May 3, 2015)

Cogsy said:


> I was in on the design and build of a largish CNC plasma cutter a couple of years ago. The one piece of advice I can give is that you really need a good automatic torch height controller.
> 
> You probably already knew but just in case you didn't...



Cogsy, thanks. I had worked that out. I have not given a thought to the electronics yet. Been trying to teach myself 3D design and have almost finished the gantry which will be laser cut and welded with locating tabs to position everything. All because this software project got me in and I happened to have a BOC 40 amp plasma cutter here! One good thing is that it has a Thermo Dynamics cutting torch.


----------



## Torfilli (Nov 21, 2015)

Just a quick hello and a big thank you!

I have just installed v10 without any major problem. The only annoyance I had were the keys on my DFRobot LCD shield (which looks like a SainSmart). My quick-fix was to replace the #define mapButton in LCD.cpp with a simple function. Certainly a tad slower than the array[] lookup, but so far I can't see any problem from that.

A quick question (or suggestion) : Is it possible to change the speed while in continuous mode ?

Again a big hooray to Rod and this project !

My code for LCD.cpp (uncomment the #define mapButton and buttonMappings[])


```
// map the buttons
int mapButton(int value)
{
  /* values depend on the version of the lcd board */
  if (value > 1000) return LCD_BUTTON_NONE;
  if (value < 50)   return LCD_BUTTON_RIGHT;
  if (value < 195)  return LCD_BUTTON_UP;
  if (value < 380)  return LCD_BUTTON_DOWN;
  if (value < 555)  return LCD_BUTTON_LEFT;
  if (value < 790)  return LCD_BUTTON_SELECT;
  return LCD_BUTTON_NONE;  // when all others fail, return this...
}
```


----------



## rodw (Nov 22, 2015)

Torfilli said:


> Just a quick hello and a big thank you!
> 
> I have just installed v10 without any major problem. The only annoyance I had were the keys on my DFRobot LCD shield (which looks like a SainSmart). My quick-fix was to replace the #define mapButton in LCD.cpp with a simple function. Certainly a tad slower than the array[] lookup, but so far I can't see any problem from that.
> 
> ...



Thanks for feedback from a happy customer. If you modify the goConTurn procedure, you may be able to add new case statements for the up and down arrows to change the frequency.

If you have a look at
goSetSpeed() you will see it incrementing/decrementing in 5% intervals and calculating a value with 

```
int speedPct = (int)((((float)((float)globals.maxStepperHz - (float)globals.minStepperHz) / (float)(Operating_Hz - globals.minStepperHz)))*100.0);
```

So maintain a similar variable and increment on up arrow and decrement on down arrow.

and then setting the speed with a call to 

```
setSpeed(speedPct);
```

Note there is not much dynamic memory left.... if you get erratic results you have a memory overflow condition and you will need to reduce the size of static strings (ie. Menu entries)


----------



## rodw (Nov 22, 2015)

Actually, I've got that a bit wrong. Speed is determined by the variable Operating_Hz
The first line quoted in my last post calculates the percentage of the range that Operating_Hz is currently set to. (between the Minimum and the maximum)
So do this calculation on entry to the goConTurn() procedure to get the current percentage and increment/decrement by 5% with up and down buttons and then call setSpeed()


----------



## Torfilli (Nov 23, 2015)

rodw said:


> Thanks for feedback from a happy customer.



That's not difficult. This is excellent code and a just-right solution.



rodw said:


> If you modify the goConTurn procedure, you may be able to add new case statements for the up and down arrows to change the frequency.



Yes, that's what I thought to do.



rodw said:


> Note there is not much dynamic memory left.... if you get erratic results you have a memory overflow condition and you will need to reduce the size of static strings (ie. Menu entries)



I have seen that space is getting really, really tight. But I have a couple of things in my head which will need much more than available, so I stripped out all the linear stuff, the devices, the safe to eeprom. My configuration is now done with a couple of #defines at the beginning. It's clearly not as flexible and configurable like yours.

My intended changes include:
- change speed within all different menus (not just continuous)
- add rotary enoder for direct turning
- add one of those IR remote controls
- maybe show RPM while turning (calculated, not measured)

I still remain true to all your core routines (apart from kicking out the globals variable) so we could still walk in parallel.

<><><><><>



rodw said:


> Actually, I've got that a bit wrong. Speed is determined by the variable Operating_Hz



Well, no. Operating_Hz currently isn't used anywhere. At least not in v10. I have written a long reply regarding this, but deleted it. Basically this is the central function, as far as I can tell:


```
void setSpeed(int spdPct)
{
  globals.maxStepperHz =  (long)((float)( Operating_Hz - globals.minStepperHz) * (float)spdPct/100.0) + globals.minStepperHz;
  globals.timerDelay = HzToTimeDelay(globals.maxStepperHz);
  Timer1.setPeriod(globals.timerDelay);      // set a timer of length in microseconds
}
```

You are modifying and operating around globals.maxStepperHz. Operating_Hz is just set once in setup() and never touched again. Because you are ramping to and from globals.maxStepperHz, and because Operating_Hz holds the MAX_FREQUENCY, it still works. So all is good functionality-wise, but by accident, so to speak. 

Again thanks for sharing.
Happy days to you, Rod!


----------



## Torfilli (Nov 23, 2015)

Another bug (?)

Apart from the Operating_Hz variable which probably should be used here as well, it seems to me that start and target needs to flip, otherwise rampSteps gets negative, which presumably stops the stepper immediately instead of ramping down. 

I am still not very clear about this frequency thing; so maybe this is as intended and not a bug.


```
void rampDown(void)
{
  startDelay =   HzToTimeDelay(globals.minStepperHz);          
  targetDelay =  HzToTimeDelay(globals.maxStepperHz); 
  rampSteps = ((startDelay-targetDelay) * globals.microSteps);  
  startRampDown = rampSteps - 3L;      // Steps to start ramping down - steps count down so we start at a high #
  endRampUp =  rampSteps -1L;                      // We don't want to Ramp Up as we are supposed to be moving
  sDelay = targetDelay;
  steps = rampSteps + 1L;              // Run enough steps to stop gracefully
}
```

Hope you don't mind that I throw all this at you.


----------



## rodw (Nov 23, 2015)

Torfilli said:


> You are modifying and operating around globals.maxStepperHz. Operating_Hz is just set once in setup() and never touched again. Because you are ramping to and from globals.maxStepperHz, and because Operating_Hz holds the MAX_FREQUENCY, it still works. So all is good functionality-wise, but by accident, so to speak.
> 
> Again thanks for sharing.
> Happy days to you, Rod!


Coming back to me now. Maybe I started to change the code to use Operating_Hz  but changed my mind (ie. got confused.)

The rampDown() and rampUp() procedures need the max and min StepperHz values. They can be changed at will until they are changed in setup or the Arduino is rebooted (which reads the values from eeprom again).

The most valuable contribution would be to recode the menu library so that it uses PROGMEM variables. This would allow the variables to live in the codespace and never get loaded into the 2k variable storage area on bootup. This (Simple?) change would solve ALL of your code space issues.


----------



## rodw (Nov 23, 2015)

Torfilli said:


> Another bug (?)
> 
> Apart from the Operating_Hz variable which probably should be used here as well, it seems to me that start and target needs to flip, otherwise rampSteps gets negative, which presumably stops the stepper immediately instead of ramping down.
> 
> ...



 I ran heaps of tests with print functions in the main loop to monitor the ISR routine to trace what was going on while ramping up and down. It is not intuitive. In the dividing functions, I am confident there are no bugs...

This bit could be buggy as what I am attempting to do is to calculate the number of steps required to ramp up and ramp down for the continuous turning procedure to avoid missed steps and loss of position. Read on and hopefully, this will become clearer. 

A Frequency of 1 Hz means 1 on and off cycle per second. This needs 2 cycles (1 for on and 1 for off)  through the ISR routine (last procedure in the file) . Think of AC power which is 50Hz.. (50 complete cycles per second) So rather than stuff around with a short pulse every now and again which is how most Arduino stepper drivers work, while the stepper is operating, the pulse goes on and off for an equal time period. This is how the data for a stepper motor is presented (eg data sheets quote frequencies).

So now we get to the ramp down and ramp up functions. Steppers generate max torque at lower speeds. Starting at a high speed/low torque might lead to missed steps (and I had a lot before I got it to run reliably). So the idea according to the Texas Instruments documentation I referenced is to start slow and ramp up by adding 1 extra step through each iteration of the ISR until it reaches the Max operating frequency. (lets just assume that takes 1000 pulses. So before we stop, we also want to ramp down as at high speed the lack of torque could cause the stepper to overrun and run for more steps than it should. So before the end point, we ramp down 1000 steps in exactly the reverse manner.

So finally, what happens if say the total movement is less than the sum of the ramp up and ramp down interval? Simple really. If say the total steps to move required was 1000, we would never get to operating speed. We'd ramp up to 500 steps, never reach operating speed then ramp down 500 steps.

The other thing that is happening in the ISR is that the number of steps from the home position is maintained at all times. Remember that you have no control over the ISR, it is just triggered by the CPU 16,000,000 per second... (16 Mhz). We must be short and sweet in an ISR as we don't have much time to do stuff!


----------



## rodw (Nov 23, 2015)

Torfilli said:


> Another bug (?)
> 
> it seems to me that start and target needs to flip, otherwise rampSteps gets negative, which presumably stops the stepper immediately instead of ramping down.




I just re-read your comment above As I said, it is not intuitive. The starting delay is bigger than the target delay because at this level we are counting the number of timer pulses between steps. Slow speed (start) = long delay. Target (fast) speed = short delay. Does that make sense?


----------



## Torfilli (Nov 23, 2015)

rodw said:


> Does that make sense?



It is slowly creeping in. Thank you for your patience and the time to reply with all these explanaitions!


----------



## Torfilli (Nov 23, 2015)

rodw said:


> Coming back to me now. Maybe I started to change the code to use Operating_Hz  but changed my mind (ie. got confused.)



In that case you could do : "%s/Operating_Hz/MAX_STEPPER_HZ/g" and fix the two syntax errors you will get at compile time. Saves a byte or two


----------



## Torfilli (Nov 29, 2015)

Ron, another (probably stupid) question:

I see you are using Timer1.initialize() in setSpeed() and in timerIsr() instead of Timer1.setPeriod(). Any special reasons for that? Surprisingly, the Timer1 inline-code says initialize() stops the timer.

I have added the speed change into continuous turning. I particularly like that I now can actually see and hear the speed, instead of trial-and-erroring it in percent-steps.

The solution has three parts. It also needs two new variables.


```
volatile long smoothRamp = 0L; // Steps to move to next speed (in continous mode)
volatile long smoothDir = 0L;  // speeding up or down in smoothRamp
```

First: Add buttons to goConTurn() as you have suggested:


```
case LCD_BUTTON_UP:
        rampTo(globals.maxStepperHz + 100);
        break;
        
      case LCD_BUTTON_DOWN:
        rampTo(globals.maxStepperHz - 100);
        break;
```

Second: Add a function to ramp to new speed.


```
void rampTo(long nextHz)
{
  /* should have some precautions against going too slow or fast */

  if(nextHz > globals.maxStepperHz) {
    // get faster
    startDelay =   HzToTimeDelay(globals.maxStepperHz);
    targetDelay =  HzToTimeDelay(nextHz);
    smoothDir = -1;
  } else {
    // get slower (or stay the same)
    startDelay =  HzToTimeDelay(nextHz);  
    targetDelay =   HzToTimeDelay(globals.maxStepperHz);
    smoothDir = +1;
  }

  globals.maxStepperHz = nextHz;
  smoothRamp = (startDelay - targetDelay) ;
}
```

Third: Add some code to timerISR(), right before your ramping if()'s


```
if(smoothRamp > 0) {
        stepcount++; stepcount++;
        stepmod = ((long)stepcount % (long)MICRO_STEPS);
        if (stepmod == 0) {
          smoothRamp--;
          sDelay += smoothDir;
          Timer1.initialize(sDelay); // adjust timer 1
        }
      }
```


Cheers !


----------



## rodw (Nov 29, 2015)

Torfilli, 

It is a great enhancement that you have coded. I did not think of it.

I had no idea I was doing something with the timer that was no quite right. But it worked 

Glad you have worked out the ramping up and down.  I would have to revisit the code but there may be a more efficient way to code the feature but after a couple of glasses of red wine with dinner , it presently eludes me.  But if it works


----------



## Donrecardo (Nov 30, 2015)

Hi Torfilli

I too use a copy of a sainsmart LCD and my left button doesnt operate as it should

I had the same problem with Chuck Fellows code but easily found the line where
I could change the ADC value that equated to "left" 
You post explains how to change LCD.cpp to do the same thing but I dont really
understand how to do it  ( its an age thing ). Is it possible you could upload a copy of your LCD.cpp so I can see exactly what and where you have changed it 
Apart from the left button Rods code is working fine for me 

Regards
Don


Torfilli said:


> Just a quick hello and a big thank you!
> 
> I have just installed v10 without any major problem. The only annoyance I had were the keys on my DFRobot LCD shield (which looks like a SainSmart). My quick-fix was to replace the #define mapButton in LCD.cpp with a simple function. Certainly a tad slower than the array[] lookup, but so far I can't see any problem from that.
> 
> ...


----------



## Torfilli (Nov 30, 2015)

Donrecardo said:


> Is it possible you could upload a copy of your LCD.cpp so I can see exactly what and where you have changed it.



Hi Don,

No problem at all; here it is.

I have commented the lines 323-327 in the original code (from the package that Rod has uploaded elsewhere here in the thread) and have added immediately afterwards my replacement-function to return a keycode from the ADC value. No magic involved.

The values in the if() statements vary from version to version, from resistors to resistors, of the shield so my version may not be cut-n-paste compatible. Just plug in the values you already have, and you should be good to go! If not, yell! and we'll find a way.

Enjoy life!

Torfilli 

View attachment LCD.zip


----------



## rodw (Nov 30, 2015)

The recent activity on this thread prompted me to gathere everything up last night and provide a concise installation guide on another thread.
http://www.homemodelenginemachinist.com/showthread.php?t=25091

Hope this makes it easier for people to adopt this sketch without wading through 22 odd pages in this thread.


----------



## Donrecardo (Dec 1, 2015)

Hi Torfilli , thanks for your help ,I'm sorry to be a nuisance but I  think I may be going insane ,( thats not unusual at my age )

I  removed my original liquidcrystal.cpp and replaced it with yours that  you just sent me , but it failed to compile  I will attach the errors  below in a file

I  put the original  .cpp file back and sure enough it worked again , all be it with the original problem of not recognising the left keypad button

I  decided I would look at the original .cpp file and compare it with the  one you sent me to see how you had changed it and thats when things  seemed to go silly
my original .cpp file is nothing at all like the  one you sent me , its completely different  as though its from a  different LCD library I will include both so you can see 


Regards Don




Torfilli said:


> Hi Don,
> 
> No problem at all; here it is.
> 
> ...



View attachment LCD ERRORS.zip


----------



## Torfilli (Dec 1, 2015)

Hi Don,

I believe that's an easy one 

The file I have sent goes into \Documents\Arduino\libraries\LCD replacing the file "LCD.cpp" that lives there. I believe you moved and renamed it into the utility subdirectory as LiquidCrystal.cpp - no good.

Let me know if this works out!

Cheers,
Torfilli


----------



## rodw (Dec 1, 2015)

Don, from your error file you are using an Arduino Mega (or compiling for the wrong chip). The Mega is a totally different beast to the Uno on which this sketch was designed. I don't think this script is compatible with a Mega.

Furthermore, you have got confused and are playing with LiquidCrystal which is not necessary. Your errors are from including a file twice so stuff is generating. The LCD library has its own copy of LiquidCrystal in a subfolder.

I would suggest you:
1. Delete the LCD folder in the library folder
2. Download the zip file on my latest thread http://www.homemodelenginemachinist.com/showthread.php?p=273833#post273833
3. Follow the instructions and install it
4. Copy the LCD.cpp file Torfilli has given you into the /libraries/LCD folder
5. edit the mapButton() procedure that Torfilli has added to the file to agree with your hardware
6. Compile the new script installed in the zip file called RotaryTable10 

I suspect however that you will also need to ditch your Mega chip and purchase an Arduino Uno compatible board and a different keyboard shield. In this case, my recommendation would be to place an order at freetronics for these items:

Arduino Compatible board ( I have used this board myself): http://www.freetronics.com.au/collections/arduino/products/eleven#
Keyboard and LCD: http://www.freetronics.com.au/collections/display/products/lcd-keypad-shield#

Prices are in AUD so currently about 70% of USD prices. There is a drop down to select other currencies.  They do have distributors around the world


----------



## Donrecardo (Dec 2, 2015)

Torfilli and Rod 

Thank you both so much for not giving up on me , I am pleased to say I now have it working  and also using Torfillis  file I have modified it so the left keyboard button now works great. You were both right I had confused my LCD and liquid crystal libraries  and I had indeed put it into the utilities directory

Rod was also right I was trying to use an Arduino Mega , the reason why was,
I have an UNO but for some reason half way through uploading it would fail. .
Because of this I tried using an Arduino  Leonardo and that was fine with version 9 
but with version 10 of the software it failed saying there was not enough program space , and because I couldnt see a way around that  I then tried the Arduino Mega

I am pleased to say I found out why the Uno failed , I renewed the bootloader and after that it worked fine . Well, I say fine , but I have yet to connect it to a stepper motor , but the LCD appears to be doing all the right things
I can also confirm it also appears to work fine on the Arduino Mega according to the LCD . It even loads into an Arduino Nano ok but as it has no way to easily connect it to a LCD shield I cant say how well it works . The only one I cant use it on is the Leonardo , which says it doesnt have enough program space

Once I have tried it with a stepper conected I will report back on how well it went on both the Uno and Mega

But once again thank you both for all your help

Don




Torfilli said:


> Hi Don,
> 
> I believe that's an easy one
> 
> ...


----------



## Donrecardo (Dec 2, 2015)

Just to let you know 

I conected it up with a 24V PSU  an MSD 415 Driver and a nema 23 stepper.
Its working perfectly on both the Arduino Uno and also on the Arduino Mega.
I know it will mean hand wiring a LCD and switches but I am going to give it a try on an arduino Nano as it seemed to compile and load up fine 

Thanks for all the help

Don


----------



## bobwho (Jan 8, 2016)

Hi Rod (hi everyone else also)
I have too been developing an arduino controller like so many others, and thought I was doing really good ... I ironed out a lot of issues and rounding errors, I been doing really well, then I stumbled across your code...  and mine is no way as efficient...

Well done Rod.

I am using a 128x64 oled display and analog joystick so I cannot simply use your code, but merely use it as a model and reverse engineer the goodness to suit my gear.  I do like the graphics abilities on the oled.
I was asking too much of the AccelStepper library, which stalled whenever I wanted to update the oled display during continuous rotate mode, so after researching I am going to try to use interrupts.  Also my C skills are not as refined (I did entry level C++ coding at tech back in the 90's, and since then I forgot all but the basics, but I am relearning quickly)

I am running this on a vertex style 10" rotary table, using a hi torque nema17 and a 3:1 reduction pulley to avoid loosing steps when milling on constant rotation.


----------



## Wizard69 (Jan 8, 2016)

bobwho said:


> Hi Rod (hi everyone else also)
> 
> I have too been developing an arduino controller like so many others, and thought I was doing really good ... I ironed out a lot of issues and rounding errors, I been doing really well, then I stumbled across your code...  and mine is no way as efficient...


Don't you just hate when that happens.   Makes you think " what was I doing".  


> Well done Rod.
> 
> 
> 
> ...


Arduino isn't really a good place to do graphics.    At least for the base model Arduino and you want to draw with higher level primitives.  The lack of power for computation is a problem even moving rasters around could use some help.  Given that Arduino is a pretty powerful chip.    


> Also my C skills are not as refined (I did entry level C++ coding at tech back in the 90's, and since then I forgot all but the basics, but I am relearning quickly)


You are lucky, back in my day it was Modula 2 in school.   

Realize though that much of what you learned in school, way back then,  doesn't apply all that much to modern C++ coding. Especially if working with a state of the art C++ compiler.  Arduino really isn't state of the art and frankly doesn't implement all of the C++ standard library, even so it doesn't hurt to upgrade your knowledge with respect to modern C++ practices.   



> I am running this on a vertex style 10" rotary table, using a hi torque nema17 and a 3:1 reduction pulley to avoid loosing steps when milling on constant rotation.




Cool!    At the rate I'm going it will be sometime before I have my own hardware to work on.    Going to Cabin Fever so who knows may get lucky with something priced right.


----------



## rodw (Jan 9, 2016)

Bobwho, great to see another convert to this code base. In your case, I would start with the very first version on post #20 as it is a simple example of an interrupt driven stepper controller. The later ISR routines got more complex as they tracked the home position and ramp up and ramp down and the like. Get that working in your environment first. 

Then, look at the additional features you wish to implement. Most of the routines that interact with the hardware are discrete modules so it should not be too hard to adopt.

Rod


----------



## bobwho (Jan 10, 2016)

Wizard69 said:


> Don't you just hate when that happens.   Makes you think " what was I doing".


yep :fan:


Wizard69 said:


> Realize though that much of what you learned in school, way back then,  doesn't apply all that much to modern C++ coding.


My coding was basic back then too, I got the hang of it but it was only an intro module first year and then a basics module the next.  I was never a developer, I went to IT support... until I became an engineer 10 yrs ago that is.


> Arduino isn't really a good place to do graphics.


Not using graphics as such, but highlighting menu choices with rectangles, and then just drawing black rectangles to clear them seems much better code-wise than reprinting text.
I made functions for displaying the headings of each menu and separate functions to update the variables but I didn't go the form route as using string arrays and PROGMEM'ing them looked way too complicated to me. I had only a few menus so simply print(F(this n that)); kept them out of ram for the sake of a few extra lines of code for each menu.


----------



## bobwho (Jan 10, 2016)

rodw said:


> Bobwho, great to see another convert to this code base. In your case, I would start with the very first version on post #20 as it is a simple example of an interrupt driven stepper controller. The later ISR routines got more complex as they tracked the home position and ramp up and ramp down and the like. Get that working in your environment first.
> 
> Then, look at the additional features you wish to implement. Most of the routines that interact with the hardware are discrete modules so it should not be too hard to adopt.
> 
> Rod


I already have home position setup and looping from 359 back to 0. I like your arc mins and secs implementation and miraculously 1 sec equals 24 full steps for me so implementing it will be easy.
I was really stuck for a while and wanted to suit your sketch to my hardware, but as your lcd library has all the form code and the keyboard isn't the same, I'm steering toward just using your ISR technique, and optimizing my code from what I have recently learnt in books and internet.
My ram usage is high at 74% so i gotta reduce my global variables and run more local variables in my functions... I'll get there.

Changing the subject now... How do you find you AL-320g lathe? I run the same thing in my shed, and for what it is I am happy with the quality I am getting from it.  I have modified mine quite a bit now and it gives better results each mod...





Cheers,
Robbie


----------



## rodw (Jan 11, 2016)

Bob, good luck with your project. Just be aware that local string variables that have been assigned a value before compiling will still consume PROGMEM global memory as the string has to be stored somewhere so it can get loaded into dynamic RAM. Menus and prompts are the worst offenders. To reduce your global RAM consumption, you have to use PROGMEM declarations or shorten the prompts. Which is why the final version has very cryptic menu items.....

The AL320G has been faultless for me. It is well used and nowhere near as pristine as yours anymore. If I had the space you have, I would have a bigger lathe with DI4 chuck and spindle brake etc but with the exception of bed length and lack of gearbox to select feeds, it has all the features and same spindle bore and swing of our much larger 3 phase lathe at work. My best mod was the 5C collet chuck but the most used mod aside from the DRO is my bed stop which lets me face each end  and centre drill multiple parts quickly and accurately without having to do one operation at a time.


----------



## RogerH (Jan 19, 2016)

Hi all,

Recently found this most useful project, well done to all involved, must have taken a whole lot of time and skill. I am a dummy on all this coding and have more trouble learning these days, ho hum. Thought I would give it a go, so after lots of problems, deleted the IDE from my PC and all Arduino files I could find and started again. I find that when I compile the sketch it gets some errors although it appears to finish and tells me how much memory etc. has been used. I wonder if someone can tell me how to fix whatever it is causing the errors below:-

C:Users\Rog\Documents\Arduino\Rotarytablechuck10\Rotarytablechuck10\.ino: In Function 'Void goDeviceMenu()':

C:Users\Rog\Documents\Arduino\Rotarytablechuck10\Rotarytablechuck10\.ino:953:31:Warning deprecated conversion from string constant to 'char*' [Wwrite-strings] addDevice("NEW Dev?");

C:Users\Rog\Documents\Arduino\Rotarytablechuck10\Rotarytablechuck10\.ino:960:33:Warning deprecated conversion from string constant to 'char*' [Wwrite-strings] loadDevice("LOAD DEV?");

C:Users\Rog\Documents\Arduino\Rotarytablechuck10\Rotarytablechuck10\.ino:967:35:Warning deprecated conversion from string constant to 'char*' [Wwrite-strings] eraseEeprom(ERASE ALL?"):

Hope this is something daft and easy to get fixed, thanks to whoever will reply with a fix. (Probably down to my stupidity)

RogH


----------



## rodw (Jan 20, 2016)

RogerH said:


> Hi all,
> 
> Recently found this most useful project, well done to all involved, must have taken a whole lot of time and skill. I am a dummy on all this coding and have more trouble learning these days, ho hum. Thought I would give it a go, so after lots of problems, deleted the IDE from my PC and all Arduino files I could find and started again. I find that when I compile the sketch it gets some errors although it appears to finish and tells me how much memory etc. has been used. I wonder if someone can tell me how to fix whatever it is causing the errors below:-
> 
> ...



Rog, it looks like the Arduino environment has changed and is issuing warnings because my code base is using older coding  conventions. There is a difference between a warning and an error in C. In this case, I would expect your code will compile, load and run Ok. 

Note that errors mean the compiler throws its hands up in the air and stops dead in its tracks. Warnings on the other hand are saying "Hey, this is not quite right' do you know what you are doing?"

I always try to eliminate all warnings in my code because sometimes thay do cause problems...


----------



## RogerH (Jan 20, 2016)

That was quick, thanks very much for your reply, it does compile and load OK, but I have not yet got all the gear to test it for function. You did a brilliant job there, I wish I could understand even a couple percent of the coding. I will continue and hope the project works OK. Thanks once again.

Rog


----------



## michvhf (Feb 19, 2016)

Rod, earlier in the thread there was talk about memory size.  I plan to use a 320x200 TFT touch screen display (it was cheap).  Is there enough memory left in the latest version for what the display routines (input and output) will need?


----------



## rodw (Feb 21, 2016)

michvhf said:


> Rod, earlier in the thread there was talk about memory size.  I plan to use a 320x200 TFT touch screen display (it was cheap).  Is there enough memory left in the latest version for what the display routines (input and output) will need?



I really have no idea about this hardware and its memory requirement.


----------



## sssfox (Feb 21, 2016)

michvhf said:


> Rod, earlier in the thread there was talk about memory size.  I plan to use a 320x200 TFT touch screen display (it was cheap).  Is there enough memory left in the latest version for what the display routines (input and output) will need?



I'm not great with these either, but I do know that if you put what you want in the code and compile it, it will tell you if there is enough room for it to fit.

That being said, I don't believe you will have a problem.


----------



## michvhf (Feb 22, 2016)

Ok Thanks!  I won't be getting to the software part for a couple of weeks yet, still finishing up the hardware.  Slight setback, broke a screw but it's not devastating.

Vince.


----------



## seafurymike (Oct 10, 2016)

Just wanted to publically say "BIG THANKS" to Rod for producing the code. I ve downloaded it today and looked over the content. I can see there has been a bucket load of work thats gone into writing it.

I've loaded the code to the UNO. Still waiting on the screen.

Q. Does anyone have a diagram of the external wiring? If not, no biggie, will read through the code again and grab the important pins from it.

Cheers
Michael


----------



## rodw (Oct 10, 2016)

seafurymike said:


> Just wanted to publically say "BIG THANKS" to Rod for producing the code. I ve downloaded it today and looked over the content. I can see there has been a bucket load of work thats gone into writing it.
> 
> I've loaded the code to the UNO. Still waiting on the screen.
> 
> ...



Michael, glad you like it.

Step and direction use a pin each. You also need to connect ground to the stepper controller for each of these signals and you may need to send +5v to an enable pin in some stepper controllers.

I think from memory, you can set the pins for step and direction  in the setup section and it will be saved to the EEPROM. It took me a long time  before I realised that the random movement in the stepper motor when downloading the script was because I was using the same pins as the USB serial port....  

Remember, it also can do linear movements but nobody has tested that section of it and because it supports multiple setups, you can use it on different machines. I had in mind to use it for a power feed in my mill.


----------



## seafurymike (Oct 16, 2016)

Its done,

Unit is up and running. Just needs an enclosure.

https://youtu.be/thxf7Uw0q2Y


----------



## rodw (Oct 17, 2016)

seafurymike said:


> Its done,
> 
> Unit is up and running. Just needs an enclosure.
> 
> https://youtu.be/thxf7Uw0q2Y



Great work Mike! I enjoyed your video.


----------



## seafurymike (Oct 19, 2016)

Just a quick note guys, in my video the segmented demonstration shows the axis move past 120 degrees. This was a minor setup error by me in that I didnt change the microstepping from 2 to 10. In short, i couldnt be arsed re-doing the video so it stayed in.


----------



## markcadcam (Oct 29, 2016)

I have assembled a stepper drive along with the Arduino and LCD for a rotary table. I downloaded all the necessary files. The program compiles fine and loads without any warnings or errors. What Im running into is, no matter what I change in the parameters the outcome is only the same. It moves only one direction and the steps per increment are always the same. It seems that it ignores all my changes. Does anybody have any ideas on what the problem is?


----------



## rodw (Oct 30, 2016)

markcadcam said:


> I have assembled a stepper drive along with the Arduino and LCD for a rotary table. I downloaded all the necessary files. The program compiles fine and loads without any warnings or errors. What Im running into is, no matter what I change in the parameters the outcome is only the same. It moves only one direction and the steps per increment are always the same. It seems that it ignores all my changes. Does anybody have any ideas on what the problem is?



Make sure you are actually saving the data in the setup menu.
Sounds like you have a mismatch between the setup and your actual wiring.  If the direction port is wrong in setup, you would probably still be able to turn one direction only.


----------



## markcadcam (Oct 30, 2016)

Hi RodW

I&#8217;m using a SainSmart LCD. I had to change the Pins to 12 and 13 for it to move both directions. That works fine now. I still am not seeing any change when I change the MICRO_STEPS or DIVIDE_RATIO. The motor turns a little over 9 turns no matter what I change. This is my present setup.

Thanks.
Mark

#define STEP_PIN             13
#define DIR_PIN              12
#define MINUTES_IN_CIRCLE    1296000      // Number od seconds in a 360 degree     circle
#define MAX_LONG             2147483646   // The biggest number we can use with a long
#define CONFIG_VERSION       "RT4"        // The Sigature to tell us we've saved stuff in the EEPROM
#define NO_DEVICE_SIG        "XXX"        // The Sigature to tell us we've got nothing in the EEPROM
#define DEV_ROTARY           0            // Device Type - Rotary Table
#define DEV_LINEAR           1            // Device Type - Linear device mm

#define SUB_VER              1            // Change on each version
#define STEPPER_STEPS_REV    200          // The number of steps per stepper
#define MICRO_STEPS          32           // set to 1 if not not using a micostepper driver, otherwise set to # microsteps
#define DIVIDE_RATIO         6            // The Dividing table ratio (eg 40 or 90)
#define MM_PER_REV           2            // Travel per mm
#define MAX_STEPPER_HZ       10000        // Maximum frequency for this stepper
#define MIN_STEPPER_HZ       5000         // Minimum frequency for this stepper
#define TIMER_DELAY          80           // 80 MIcroseconds between interrupt ticks
#define JOG_STEP_ANGLE       1800L        // 0.5 degrees (30 seconds)

struct globals_t  // Size = 40 bytes
{


----------



## rodw (Oct 31, 2016)

markcadcam said:


> Hi RodW
> 
> Im using a SainSmart LCD. I had to change the Pins to 12 and 13 for it to move both directions. That works fine now. I still am not seeing any change when I change the MICRO_STEPS or DIVIDE_RATIO. The motor turns a little over 9 turns no matter what I change. This is my present setup.



I think you have totally missed the level of sophistication in this script. You do NOT configure it by editing the code. Thats what the setup menu is for. So rollback to the original code. Modify it for your LCD if required. Then compile and download it. 

Then from within the menu structure on the Arduino, select Setup, configure it for your hardware including the pins you are using. Save the setup. It is then saved in flash RAM and retrieved on startup. You should be right to go.

Note that multiple devices are supported and these are numbered from 0. This lets you use the same electronics for multiple devices. Linear devices that just go back and forth can also be configured. Eg.for a motor drive for a miling table X axis.


----------



## Foozer (Oct 31, 2016)

#define STEP_PIN             1
#define DIR_PIN              2

Am a novice with arduino, however those two pins [1, 2] are interrupt pins. Would seem that changing the pin numbers as done to 12, 13 [non-interrupt] will defeat the purpose of the timer interrupt driven scheme.


----------



## rodw (Oct 31, 2016)

Foozer said:


> #define STEP_PIN             1
> #define DIR_PIN              2
> 
> Am a novice with arduino, however those two pins [1, 2] are interrupt pins. Would seem that changing the pin numbers as done to 12, 13 [non-interrupt] will defeat the purpose of the timer interrupt driven scheme.



No, that doesn't matter as we are using timer interrupts which are tied to the clock, not a physical port. I think the real problem is that the config remains incorrectly configured with a mismatch between physical ports and what is stored in eeprom that is sent to the stepper controller. If you think about it, any pin will work for the direction signal and the stepper will go left or right depending on whether the port is high or low. But if you  are changing the direction value on the wrong port, it will be permanently stuck in either forward or reverse motion.


----------



## Foozer (Oct 31, 2016)

rodw said:


> But if you  are changing the direction value on the wrong port, it will be permanently stuck in either forward or reverse motion.



Time to hook up my little cigar box stepper test and load your program

if (setupForm.isCurrent(sDirPinField)) {
          globals.DirPin = sDirPinField.value();

input value from sDirPinField becomes DirPin [High, Low] value becomes actual direction ? - - Oh Boy . . .


----------



## markcadcam (Nov 1, 2016)

RodW

I got my controller configured and everything works fine now. Thanks for your help and your great program.

Mark


----------



## rodw (Nov 1, 2016)

Foozer said:


> Time to hook up my little cigar box stepper test and load your program
> 
> if (setupForm.isCurrent(sDirPinField)) {
> globals.DirPin = sDirPinField.value();
> ...



Long time since I've looked at this code. What you are looking at is code using the 3rd party LCD class that drives the menus and data entry in one of the libraries. Classes are part of C++ and did not exist in the original C language. 

So if the current field  being edited is the direction pin field, get the value from the LCD class and store it in the globals structure. LOW and HIGH are defines in the Arduino and are the same as TRUE and FALSE  which is a fancy way of saying 1 or 0.

So now we know the pin  to write direction to. All globals are stored in a structure so it is super simple to read and write them all to the EEPROM.

So in a rotary table, we are interested in moving CLOCKWISE or ANTICLOCKWISE  which are DEFINED  to be  LOW and HIGH. Different tables may have a different default rotation direction so we can change the definition around by swapping the CLOCKWISE/ANTICLOCKWISE LOW and HIGH defines.

So in theory the code should become more readable even if it is compact and efficient as there is no room for verbose code!

So Foozer, finally, the last procedure in the file is the actual timer interrupt service routine (ISR). It is attached in the setup routine and taken from the default setup in Hz. THe trick  here is that a Hz is one cycle per second so that implies 2 passes through the ISR, one for off and one for on. Thats why i have some conversion routines as it makes more sense to configure a stepper motor in Hz as this is how the data sheet is written. 

Here endeth the lesson.  Good luck!


----------



## rodw (Nov 1, 2016)

markcadcam said:


> RodW
> 
> I got my controller configured and everything works fine now. Thanks for your help and your great program.
> 
> Mark



Glad you got it going. I was thinking that if you compiled and ran the default program, the EEPROM would be overwritten with the default data.  If you subsequently edited the globals in the code and recompiled, the EEPROM data did not get overwritten. Because the data existed in EEPROM, it would be retrieved and stored over the top of your globals data.


----------



## Foozer (Nov 1, 2016)

rodw said:


> So in theory the code should become more readable even if it is compact and efficient as there is no room for verbose code!
> 
> So Foozer, finally, the last procedure in the file is the actual timer interrupt service routine (ISR).
> 
> Here endeth the lesson.  Good luck!



Got it, naw I don't, but it's percolating . .

Didn't like having to write over and over the stepper commands in the script so wouldn't exactly call it a library but made a cpp to hold the blash blah blah then in script one line does it
Stepper.CW(dirR,stepR,rateR);
Stepper.CCW(dirR,stepR,rateR);

void StepperXY::CW(int pin1, int pin2, int pin3)     // pin1 dir, pin2 step, pin3 rate microseconds 
{ 
  pinMode(pin1, OUTPUT);     // dir 
  pinMode(pin2, OUTPUT);     // step 
  digitalWrite(pin1,        HIGH); // CW
  delayMicroseconds(5); 
  if (digitalRead(pin1) == HIGH)  // probably not needed
  { 
    digitalWrite(pin2, !digitalRead(pin2)); 
    delayMicroseconds(pin3); 
  } 
}

It's always fun to learn something new, just keep the aspirin coming .


----------



## rodw (Nov 2, 2016)

Foozer said:


> Got it, naw I don't, but it's percolating . .
> 
> It's always fun to learn something new, just keep the aspirin coming .



I try and avoid using delay() as it locks the Arduino to see whats going on. Here's how I did it after displaying the welcome screen while still servicing the keyboard.


```
while(1){  // Delay 2 seconds without using delay();
     currentMillis = millis();
     if(currentMillis - previousMillis > interval) {
        previousMillis = currentMillis;
        break;  
     }
     event = lcd.getButton();
   }
```

Rolling right back to Version 2 of my script, you can do it with interrupts in 200 lines of code. Still uses the LCD library. I think V1 had about 150 lines of code to prove the interrupt approach would work.

This simpler example will make it much easier to learn whats going on. Here's the minimalist ISR routine. In the ZIP file it still includes the original sample code to flash the LED so I knew what was going on but I've removed that below as its a distraction.


```
void timerIsr()
{
    // Toggle LED
  if(steps){
      state = state ^ 1;
      digitalWrite( stepPin, state );
      steps--;
  }
```

So for each alternate call to the ISR, we need to swap between LOW or HIGH to make the stepper move. We do that with the state variable

```
state = state ^ 1;
```
This line does a Bitwise XOR (Exclusive OR) with 1
so:
0 XOR 1 = 1 and
1 XOR 1 = 0

which is  a lot simpler (and faster) than 

```
if(state ==1) 
   state = 0
else 
   state = 1;
```
Remember, speed is king in the ISR! 

View attachment RotaryTableChuck2.zip


----------



## Foozer (Nov 2, 2016)

rodw said:


> I try and avoid using delay() as it locks the Arduino to see whats going on. Remember, speed is king in the ISR!



Getting dark earlier so it's time to look back into interrupts . .
Oh ya - Your program works on my little cigar box stepper test platform - Had to get the values from freetronics and rig up the voltage divide for the buttons - Turn it on, push some buttons and away it goes . . .

I know i'm missing something - if I run
for(int jog; jog<400; jog++);  // 400 steps per rev
{
digitalWrite(thisPin, !digitalRead(thisPin));
delayMicroseconds(600);
)
It's only 1/2 revolution whereas

for(int jog; jog<400; jog++);  // 400 steps per rev
{
digitalWrite(thisPin, LOW);
delayMicroseconds(600);
digitalWrite(thisPin, HIGH);
delayMicroseconds(600);
}
is a full turn - But what it is I don't see . . .


----------



## rodw (Nov 3, 2016)

Foozer said:


> Getting dark earlier so it's time to look back into interrupts . .
> Oh ya - Your program works on my little cigar box stepper test platform - Had to get the values from freetronics and rig up the voltage divide for the buttons - Turn it on, push some buttons and away it goes . . .
> 
> I know i'm missing something - if I run
> ...



Because the first example writes to the stepper pin half as often as the second.

Eg first loop has 1 x digitalWrite (either on or off each iteration)
second loop has 2 x digitalWrites (both on and off each iteration)

Good luck with it.


----------



## Maxmekker50 (Apr 19, 2017)

Hello In all, Fight Contributions I am quite dull What you can

I Need Help An Old Norwegian, I Have a rotary table Ratation 1:72 Having read through the forum for a few days now, Don mostly but not the relationship between 1:72 ratation And Nema motor 23 looks we are talking about 200 step 400 step . Can anyone help me What motor should I buy and possibly how to change code in arduino ?? I have all the parts in place but can not find this out with engine and ratation, HAS TB6560 3A stepper motor driver that I thought I'd use. If eny have the file for 1:72 ratation and can giwe me Tips which motor to use  , I can do it *_*

Thanks All
And I am very grateful for the help here

Call me a dummy but at this trips I checkmate


----------



## rodw (Apr 20, 2017)

If you go.to this thread
http://www.homemodelenginemachinist.com/showthread.php?t=25091

, the installation  is set out step by step. Pretty much any NEMA23 will have enough power to turn a rotary table.provided.if has enough volts. I found 19v was not enough and went to 48v. Most steppers are 200 steps per rev. I get my steppers from steppersonline who I think have an .eu site. Is get a 4 wire 2.8 amp stepper with your controller

Once the software is installed, go to the setup menu to set the software.to agree with your Arduino  pins etc.


----------



## sns5400 (Aug 30, 2017)

Hello,
This look fine but, i try to compile this for the arduino uno, and get a error missing Boolfield.h can i find this somewhere ?


----------



## rodw (Aug 30, 2017)

sns5400 said:


> Hello,
> This look fine but, i try to compile this for the arduino uno, and get a error missing Boolfield.h can i find this somewhere ?



That file is part of the LCD library. PLease start again on this thread.
http://www.homemodelenginemachinist.com/showthread.php?t=25091
Make sure you read it all and update the procedure as per my post near the end of the thread.


----------



## sns5400 (Aug 31, 2017)

This is the good point to start and download the code but....
After compile and upload the code in arduino uno, now i have only one button, (right) works ?

Any suggestion ?


Start point:
http://www.homemodelenginemachinist.com/showthread.php?t=25091


----------



## rodw (Aug 31, 2017)

sns5400 said:


> This is the good point to start and download the code but....
> After compile and upload the code in arduino uno, now i have only one button, (right) works ?
> 
> Any suggestion ?
> ...



You have just learnt that nothing on the Arduino is plug and play 

I would say your LCD/keyboard shield is not compatible with the Freetronics hardware this was designed for. If you go to www.freetronics.com.au you should find the resistor values they use for the keyboard together with examples that show the cutoff values for each button. Then compare the values with your hardware. If you go through this thread, you will find an example how another member modified the library code for different hardware.

Or you could take the easy way out and order a freetronics shield.


----------



## sns5400 (Sep 1, 2017)

Hello,
i have the same problem, of my keys only right button work.
Its a robot shield with 6 button.

Is it possible to upload your LCD.cpp file

Thank in advance

Pieter


----------



## Foozer (Sep 1, 2017)

sns5400 said:


> Hello,
> i have the same problem, of my keys only right button work.
> Its a robot shield with 6 button.
> Pieter



DFRobot? Two versions different return values .
From their info page . . . 
 if (adc_key_in > 1000) return btnNONE;       // For V1.1 us this threshold     if (adc_key_in < 50)   return btnRIGHT;       if (adc_key_in < 250)  return btnUP;      if (adc_key_in < 450)  return btnDOWN;      if (adc_key_in < 650)  return btnLEFT;      if (adc_key_in < 850)  return btnSELECT;       // For V1.0 comment the other threshold and use the one below:    /*      if (adc_key_in < 50)   return btnRIGHT;        if (adc_key_in < 195)  return btnUP;       if (adc_key_in < 380)  return btnDOWN;       if (adc_key_in < 555)  return btnLEFT;       if (adc_key_in < 790)  return btnSELECT;       */


----------



## fugalguido (Nov 23, 2017)

Very frustrated, can someone please help me?.What is the proper operation of the buttons ( owners manual)? When it boots up it shows divide #... up/down starts. If I push select, it  goes though various main menus. What button do I push to select ( lets say configure ). When I push the right button it seems to mimic the select button but in the opposite direction of the menus.


----------



## rodw (Nov 23, 2017)

The reason why you are frustrated is that you are using different hardware to what was specified. Arduino is not a plug and play environment. Therefore, it is up to you to change the code to suit your hardware or if you can't do that, adopt the exact hardware that has been specified in terms of the Arduino itself and the LCD display shield.

The reason why your buttons do not work as expected is that the random LCD shield you have used uses different resistor values for the buttons on the analog port to what the original Freetronics shield uses. 

Some people have modified the button handling code in the LCD library for different hardware and shared their results here. If you wish to persist with your current hardware then find that code, review the documentation for your LCD shield and that of the Freetronics shield, make your modifications and your buttons should work. 

This is not an entry level Arduino script or a tutorial on how to use the Arduino, nor is this a software forum. The LCD library, my extensions to it and my interrupt code push the poor little Arduino UNO to the limits and required terse and efficient code written for specific hardware. If you adopt different hardware, its up to you to take the time to READ the whole thread as chances are somebody has solved the problem before you.


----------



## fugalguido (Nov 23, 2017)

I don't know if the buttons are working correctly or not. I don't want a chase a problem that doesn't exist . I need a discussion on the operation of said buttons  or a flow chart. I could find no dicussion on the operation of this software from a button operation viewpoint in the three plus threads on this board, if there is, could some please point where this is located. I know about the analog to read values in to the A0 pin between different boards.


----------



## rodw (Nov 24, 2017)

fugalguido said:


> I don't know if the buttons are working correctly or not. I don't want a chase a problem that doesn't exist . I need a discussion on the operation of said buttons  or a flow chart. I could find no dicussion on the operation of this software from a button operation viewpoint in the three plus threads on this board, if there is, could some please point where this is located. I know about the analog to read values in to the A0 pin between different boards.



You've told me you have a problem. I've told you what your problem is. Its up to you to either use the supported hardware or modify the code to suit your hardware. There is no need for discussion except to say:

The original LCD library was written by a third party specifically for the Freetronics LCD display. His code is on github and I did link to it in these threads by way of acknowledgement. I originally had commenced writing  my own number entry routines and menuing system but his were so good, I adopted his library and extended it as I was using Freetronics hardware. His library is high performance and uses a separate C program designed to run on a desktop pc to generate the keystroke handling routine based on the resistor values so his code is very cryptic in that area. 

Some people on this forum replaced his high performance generated code with their own and shared it on this thread. It is possible to modify his generator code to write to the Arduino Serial port so it can display the required code so you can cut and paste it.

I extended some of his input routines to handle different number formats including entering degrees, minutes and seconds. But the fact remains it is written for specific Freetronics hardware......

So finally to be 100% clear,  to get your keyboard working it's not my code you need to modify but the third party LCD library I have used.


----------



## fugalguido (Nov 24, 2017)

Ok, got the buttons to work thanks to Torfilli's(sp) LCD.cpp code. But I need some operator directions as I mentioned previously on the use of the menu's. When I get to the setup menu and go to setup the step pin #, to say pin#2, I change it to from 1 to 2 the up down buttons, then rotate through to the Save and select yes, then hit select button. It doesn't save. It appears to reboot, when I go back to the setup menu Step pin is still at #1. 



Again to be 100% clear, I need a operators manual or instruction on the use of the menus, not a discussion on the hardware.


Also another question where to you hook up the enable control from the drive. On my previously used programs a pin was defined for enable.


----------



## rodw (Nov 25, 2017)

fugalguido said:


> Ok, got the buttons to work thanks to Torfilli's(sp) LCD.cpp code. But I need some operator directions as I mentioned previously on the use of the menu's. When I get to the setup menu and go to setup the step pin #, to say pin#2, I change it to from 1 to 2 the up down buttons, then rotate through to the Save and select yes, then hit select button. It doesn't save. It appears to reboot, when I go back to the setup menu Step pin is still at #1.
> 
> 
> 
> ...



Well it seems to me that a discussion on the hardware resolved your buttons issue.

I don't have a configured Arduino to guide you so am unable (and unwilling) to document a user manual. 

Hitting save in the setup menu will save the parameters to the UNO's EEPROM and it should be read from there on startup. And yes, it reboots at this point to force reload of the new config. Oh wait, you are not using a UNO are you? A 32 bit Arduino might be a bit different in the EEPROM department. As I said use different hardware, you are on your own.

Configs are numbered sequentially from 0 and the current default config # is saved in eeprom and loaded on startup. Its possible your system is getting confused and not loading the config you changed. Load Config 0 and see if its correctly configured. Turn it on and off and see if the same config is loaded and check the parameters after startup. There is also a linear config type that might be used for drilling holes or as a milling machine table motor drive so make sure its a rotary config you are using.

If you go through the various #defines at the start of the program, you should be able hardcode the default step and direction pins but that will probably break the multiple config functionality (which also depends on the EEPROM anyway).

In my experience, the stepper enable signal is actually a disable signal so if it goes to +5v, it disables the stepper motors. Documentation for  the stepper drivers I have does not recommend connecting it. If you wanted to add an estop button, you could steal 5 volts from the Arduino (unless its a 3.3 volt variety) and pass it through the estop button to the drive (dis)enable input. You'd just need to check which state (high or low) disables the drives.

Many people are using this software without an ounce of trouble and you are the first to report issues loading configs. It will be related to your hardware.
Let me know how you get on.


----------



## fugalguido (Nov 25, 2017)

Thanks for the reply. Yes, an UNO. Here what I did on your recommendation , Changed the DIR to 0, changed the STEP to 0, hit Save=yes. After rebooting up, the Dir did change to a 0, but STEP stays at 1. Went into the program IDE as per your advise, in the # define changed STEP_PIN to 0, uploaded, went into the setup on the UNO, STEP stayed at 1. The problem is with the STEP pin not changing states both thru the on board programing or the IDE (it is stuck on one) I also tried to change the STEP_PIN to a 4 in the #define , just see what would happen, no change stays at 1. Found another problem, can't change the  #define DIR_PIN though the IDE, but can change it though the UNO and save it. 

So in summary;

STEP pin can't be changed and saved at all from either the IDE or the UNO.

DIR pin  can't be changed and saved from the IDE, but can from the UNO.


----------



## fugalguido (Nov 25, 2017)

I just tried hooking up the Uno to the stepper driver using the pins the Uno is stuck on in RodW's program(Step pin 1 and dir pin 2), no movement in any function. I went back to Chuck's program and the Gary Liming program, everything works great using their programs. Did this to verify the drive, motor and wiring there ok. Have the config menu settings as follows DevTyp= Rotary /JgAn=30 seconds /DirP=2/StpP=1 /Stp/Rv=200 /M/step=1:1 /D/Rat=1:1 /MaxHz=10k /MinHz=5k, Also in the Contin menu (I am assuming this means continuous rotation) the only way to get out this menu is to reset the Uno, is this the way it is supposed to work? 

I did change the GoDivde portion(bug?) as you advised in the other thread after I got the keypad working. This Uno was just purchased in the last 6 months so it is up to date a far as the revisions. The keypad buttons seem to work properly now, so what could be the problem now.

I could scope the two pins for switching signals, but like said they work on the other programs using those pins, so I don't think they're the problem. Whats next?


----------



## rodw (Nov 25, 2017)

If you have to reset the UNO to escape out of Continuous Turn, I think there is still a button problem. The shields I used seemed to use very poor quality switches and I actually wore switches out when developing this sketch so I replaced the shield as I had similar problems to what you are experiencing. I would check the button function with a simple sketch (hopefully provided by your shield manufacturer) to confirm all buttons work as expected and do not stick. (or scope the A0 output).

From your settings, I might know what your problem is. But first let me explain the config settings

StepP = Step Pin
DirP = Direction Pin
JgAn = the amount the table jogs in jog mode
Stp/Rv = 200 = standard 1.8 degree stepper eg steps per revolution)
M/step = Microstepping (eg. Gecko stepper driver would need 10:1)
D/Rat  = 1:1  this is the gearing ratio. a standard Rotary Table might be 90:1 or 40:1
MaxHz = 10k this is the fastest speed (steps/sec) that the stepper will operate at
MinHz  = 5k this is the slowest speed the stepper will operate at. (stepper starts at MinHz and ramps up to MaxHz)

I believe that your frequency settings are far too high for a 1:1 stepper config with no microstepping. From my experience, the average stepper maxes out at about 450 rpm. (7.5 rev per second)
So the maximum frequency your stepper can operate at is 7.5 * 200 = 1500 steps per second (1.5k) and you have 10k.
With my 10:1 microstepping, the maximum frequency I could do was about 15,000 but I backed off to 10,000 Hz to be safe. You should do the same
You will need to set MinHz and MaxHz to say 750 and 1000 for native resolution

With hindsight, pins 1 & 2 are not an an ideal choice because they are used for USB communications. You get some buzzing from the stepper if connected when uploading a new script. Selecting say pins 3 & 4 might be a better option which avoids this.


----------



## fugalguido (Nov 26, 2017)

So, the JgAn if this is set to 1 degree, then each push of the right or left button the table moves 1 degree? 

If it was working right, to get out of the continuous turn hit the Select button?

I think that I am going to build the button circuit on a separate board using industrial quality buttons and some 1% resistors to mimic the keypad. I did high end audio/analog design for 20+ years so I have the parts.

I will change the freq. setting to what you recommend and see what happens. I will report back, thanks.


----------



## rodw (Nov 26, 2017)

fugalguido said:


> So, the JgAn if this is set to 1 degree, then each push of the right or left button the table moves 1 degree?
> 
> If it was working right, to get out of the continuous turn hit the Select button?
> 
> ...



Sorry about the cryptic prompts but they kept getting shorter as the memory got tighter. If it is not a faulty button, it is possible for some reason that you have a memory overflow error. This could occur if the later versions of the compiler consume more static RAM than the earlier compiler versions.

However, I've not had any other reports of this happening from recent users of the sketch.

Yes, *JogAn *sets how far a rotary table moves on each press of the jog buttons
Yes, Select should Exit and go back one level in all of the procedures.  
When Continuous turning, it will ramp down down to a stop on exit.

The code is very readable. All procedures that actually do something (as opposed to getting user input) start with "go" as in
goDivide() and goConTurn()


----------



## fugalguido (Nov 26, 2017)

Is there a way to see if memory overflow is the problem? I am using 1.8.1.  I see that the newest is 1.8.5.

Also, if I mimic the button circuit on the keypad that you used, I should go back to your original  keypad/LCD program instead of Torfollis (sp) right, even though I am using the my LCD portion of the keypad?


----------



## rodw (Nov 27, 2017)

fugalguido said:


> Is there a way to see if memory overflow is the problem? I am using 1.8.1.  I see that the newest is 1.8.5.
> 
> Also, if I mimic the button circuit on the keypad that you used, I should go back to your original  keypad/LCD program instead of Torfollis (sp) right, even though I am using the my LCD portion of the keypad?



There is no way of knowing except things stop working. Just shorten a few more menu prompts and see if things change. What the problem is that the Arduino stores text variable data in static RAM but on startup, it copies these over into limited dynamic global RAM, effectively creating 2 copies of each string. For unchanging menu text, this is very wasteful of resources. There is a way to use the static versions of strings using the PROGMEM definition but the text cannot be changed.

The most useful extension anybody could make to this script would be to modify the LCD library so PROGMEM variables could be used for  all of the menu prompts. This would free up an enormous amount of global memory.


----------



## Harrih (Jan 3, 2019)

@rodw
Hi there,
I hope this thread is still being monitored.
New to both this board and thread so hello to all.

I am particularly intrigued by this thread as it solves many of the difficulties I have been facing attempting to implement more or less exactly what you have achieved here,
so would like to try using your code and see how it goes.
There are a couple of things i hope to slightly modify for my applications.
First is to recompile it to run on a teensy3.2 micro so all the lcd stuff will have t change also pinouts etc.
Other thing is to introduce backlash compensation, so that apart from incremental and continuous jog modes the motor always approaches the mark from the same direction
(even if that means overshooting and then backing up).
I understand this project is somewhat historical so probably well out of mind by now
but if you had any suggestion re the best place to start inserting backlash compensation would be appreciated.
There are 2 applications where I would find this very useful
1 being a rotary table for a small machining centre
the second as a downfeed for a surface grinder where measurements are in microns and the work must always be approached from one direction

Hope to hear from you
regards
Harry


----------



## rodw (Jan 3, 2019)

Harry, I did think about backlash but decided that if you only travelled in one direction which is the usual case there was nothing to worry about compensating for.

So just thinking out loud, Backlash only becomes an issue when you change direction. I think you'd have a variable that said how many steps or degrees of backlash. You should be able to include this in the global setup structure and modify the setup input screen so you could edit it. Then just mantain a global flag that said direction had changed and reset it after the first movement. That way if the flag was set, you'd just add the backlash compensation to the number of steps to move (and rest the flag at the end). I think it would be pretty simple to incorporate.


----------



## dazz (Jan 3, 2019)

Harrih said:


> @rodw
> 
> I understand this project is somewhat historical so probably well out of mind by now
> but if you had any suggestion re the best place to start inserting backlash compensation would be appreciated.


I haven't looked at the code but somewhere in there I would expect to find a +ve/-ve or boolean value to define the direction of the next rotation.
It would only be necessary to add a statement that does this on completion of the rotation:

If direction negative, move -10 steps and then move +10 steps

The number of steps will depend on the measured backlash etc.


----------



## Scott_M (Jan 3, 2019)

I can see a few applications where keeping track of rotation may be useful but, I think that if you have more backlash in your rotary table than you can live with tolerance wise , this won't fix it. The stepper will be backlash free and counts very well so it will be where it is supposed to be regardless of direction. The mechanical backlash in the rotary table is the issue and as soon as your tool hits the work it will move the work/table regardless of how accurately it was positioned.

What is really needed is a way to automatically apply a brake to the table after the move and release it before the next move. This would solve most backlash induced issues.

We almost always go in one direction so the backlash wouldn't be a problem and for those few occasions you do have to back up , adding some code to backup a little further and then come to position in the right direction would be easy.

Scott


----------



## rodw (Jan 3, 2019)

Dazz, yes, there is a direction flag that is 1 for one way and 0r the other (globals.DirPin). Backlash only bites when the direction changes. There is a function called GoDivide() that responds to direction buttons and sets the distance to move.

So maybe something like this (one direction only shown)

```
while(event != LCD_BUTTON_SELECT){
      event = lcd.getButton();
      switch(event){
        case LCD_BUTTON_LEFT:
          flag++;
          thisDiv--;
          divLeftOver -= remainder;
          if(thisDiv < 1)
            thisDiv = divisions;
          if(globals.DirPin != ANTICLOCKWISE) // do we need to add backlash?
                 backlashsteps = global.backlash;
          else
                 backlashsteps = 0;
          digitalWrite( globals.DirPin, ANTICLOCKWISE );
          break;
        case LCD_BUTTON_RIGHT:
```


then later:


```
SetSteps((stepsPerDiv + adjustSteps + backlashsteps) * 2, 1);
```

Note this code might be a bit different to what is presented to make sure there are no missing steps. Details and code are in this thread so start with the GoDivide() function shown there:
https://www.homemodelenginemachinist.com/threads/interrupt-driven-rotary-table-controller.25091/


----------



## Harrih (Jan 3, 2019)

Thankyou for the swift and multiple responses,





rodw said:


> Harry, I did think about backlash but decided that if you only travelled in one direction which is the usual case there was nothing to worry about compensating for.
> 
> So just thinking out loud, Backlash only becomes an issue when you change direction. I think you'd have a variable that said how many steps or degrees of backlash. You should be able to include this in the global setup structure and modify the setup input screen so you could edit it. Then just mantain a global flag that said direction had changed and reset it after the first movement. That way if the flag was set, you'd just add the backlash compensation to the number of steps to move (and rest the flag at the end). I think it would be pretty simple to incorporate.



So if I understand right what you suggest, is in a change of direction adding  the step count that corresponds to the backlash present and so accounting for it.
My preference however is more to imitate what one tends to do manually, which is to always approach the mark
from one direction only(sloppy lathe cross slide comes to mind)
This will require either backing off , or deliberately overshooting the mark by some amount and then approach from the same direction in all cases as Scott describes above.
I do have  pneumatic locks on this table by the way and the use is for multi axis positioning/indexing in a CNC mill.

What really intrigues me however is potential use as an automated downfeed in a surface grinder I am rebuilding.
In this case 1 micron is a measurable and settable amount of travel, whereas the total backlash between the handwheel and the wheel head is in the order of 5deg of handwheel movement(5micron). This requires a very consistent technique in setting the height. There are other issues to deal with also such as wheel dressingand its effect on position but that's for another time.

Again thanks for your thoughts and I will carry on from here

Cheers 
Harry


----------



## Harrih (Jan 3, 2019)

Crossed posts , 
will look at this carefully
Harry



rodw said:


> Dazz, yes, there is a direction flag that is 1 for one way and 0r the other (globals.DirPin). Backlash only bites when the direction changes. There is a function called GoDivide() that responds to direction buttons and sets the distance to move.
> 
> So maybe something like this (one direction only shown)
> 
> ...


----------



## rodw (Jan 3, 2019)

Harry, What you have described is a one way movement so there will be no need to back off the current position when moving down. Backlash will not be an issue as stepper holding torque will keep the current position locked. Provided the stepper and gear train allow the stepper to give 1 micron resolution, you should not have any issues.

What you could consider is to use another output pin to activate your pneumatic lock. This could be done in the SetSteps procedure

```
void setSteps(long sSteps, int sWait)
{
int oldSpeed;

  rampSteps = (long)(((float)sSteps / 2.0));      // the number of on/off cycles
  startDelay =   HzToTimeDelay(globals.minStepperHz);        
  targetDelay =  HzToTimeDelay(globals.maxStepperHz);
  if(((startDelay-targetDelay) * globals.microSteps) < rampSteps) // Don't go faster than the max stepper speed
    rampSteps = ((startDelay-targetDelay) * globals.microSteps);
  startRampDown = rampSteps;           // Steps to start ramping down - steps count down so we start at a high #
  endRampUp = (sSteps - rampSteps);    // Steps to stop ramping up -- steps count down so we start at a high #
  oldSpeed = sDelay;                   // save the old speed
  sDelay = startDelay;                 // set starting delay
  Timer1.initialize(sDelay);           // set the interrupt timer
  stepcount = 0L;                      // Zero the step counter
  // Always Unlock solenoid here
  steps = sSteps;                      // GO for it
  if(sWait){
    while(steps){
      ;                                  // Wait until done
    }
    // lock solenoid here
  }
  sDelay = oldSpeed;
}
```

At this point, the move has been resolved to the number of stepper steps required to complete the move (sSteps).

This procedure takes a parameter to tell it if it should wait for the move to complete (dividing) or not (jogging)
The steps variable is what the interrupt routine counts down while moving the stepper motor. So you should always unlock the brake here in case the last move was a jog and lock it if sWait is true. You'd also need to lock the solenoid at start up and at the end of the rampDown() procedure so it was locked after any jogging moves. You'd probably need to add some dwell time to allow the solenoid to open and close so I would write a seperate procedure for that

```
int lockBrake(int lock)
// locks or unlocks brake depending on the state of the lock parameter
{
   if(lock){
      //lock the brake
   }
   else{
      //unlock the brake
   }
  // apply a dwell period so the solenoid has time to activate.
}
```


----------



## rodw (Jan 4, 2019)

Harrih said:


> Crossed posts ,
> will look at this carefully
> Harry


Just be aware that the code needs to be duplicated for the CLOCKWISE direction under 

```
case LCD_BUTTON_RIGHT
```


----------



## stragenmitsuko (Jan 8, 2019)

Quick question guy's , is there a general concensus on wich pins to use for step and dir ? 

D3 D4 D5 D6 D7 D8 D9 ( pins 4 ...10) are sed by the shield if I understand corrctly . 
D0 D1 ( pins 1 &2 ) are -sometimes-  used for serial communication , so better to avoid also . 

That would leave D2 and D10 for step and dir . 

The reason I'm asking is that I'll be making a dedicated pcb for this with a nano  and I would prefer 
to get it right right away instead of having to cut traces . 

Also , Rod , I tried to DL the genlookup.c program , but I'm getting page not found . 
Offcourse I'll use thesame values as the original shield so it shouldn't be an issue . 
But if you still have it somewhere , I'de like to take a look at it . 

Big thx for this wonderfull  project .  It will keep me busy for the coming cold months . 

What I like most about it is the possability to use it on multiple devices without having to recompile . 

A feature I would add , if I had the skills to do it , is a home (proximity or optical or hall ) switch . 
That would allow the device to home and then start from a known fixed position . Eg for a rotary table , one slot parallel to the x axis , or for a dividinghead one jaw parallel to the xy plane wich is handy when working with square or hex stock  . 
Just thinking out loud  .


----------



## rodw (Jan 8, 2019)

The Source code for the LCD library has moved in github
https://github.com/rweather/arduino-projects
genlookup is in a subfolder https://github.com/rweather/arduino-projects/tree/master/gen
And the LCD library is in this subfolder https://github.com/rweather/arduino-projects/tree/master/libraries/LCD

There are some good resources using prox switches with the arduino on youtube. Its not hard you just need the prox sensor in the correct voltage range and usually a pull up or pull down resistor depending on the sensor type PNP or NPN. 

It does not matter much which pins to use, just if you use the serial pins, its best to turn off the stepper power as you get random movements from the serial port data when you update your sketch. I started with those pins but moved them later to do this(Which you can do in the config settings). 

ScottM uses a prox sensor to trigger indexing under Gcode control


----------

