Tips for Arduno software for Rotary Table Controllers

Home Model Engine Machinist Forum

Help Support Home Model Engine Machinist Forum:

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

rodw

Well-Known Member
Joined
Dec 2, 2012
Messages
1,146
Reaction score
340
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:
Code:
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.
Code:
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.

Code:
#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:
Code:
DegreeField degreeField(mainForm, "Rotation", 360, DEGREEFIELD_READ_WRITE);
and this:
Code:
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

Code:
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:

Code:
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();
}

Code:
// 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
Code:
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!
 
Last edited:
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 :confused::confused::confused:

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

Paul.
 
Last edited:
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.
 
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 :confused::confused::confused:

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. :confused:

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.
 
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 :confused::confused::confused:
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.
 
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!
 
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.
 
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
 
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:
Code:
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.
 
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.
 
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.
 
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.

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.
 
Caveat Emptor

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

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
 
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.
 
Last edited:
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.
 
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
 
Back
Top