Wednesday, May 6, 2020
Building a Diesel Shay Pt 2
In Pt 1 I said something about looking for an HO Bachmann Shay on eBay. I did look but in the end decided on an On30 Bachmann Shay. The more I looked at the HO version the more I thought the wheels looked too small. Nuff said. I found a really great deal for a dismantled On30 Shay that had metal gears from Northwest Short Line. It also had bags of spares and a wood cab kit. Most importantly.....it ran. As soon as I got it I dismantled the cylinders and boxed in the driveshaft to resemble a transfer case. It looked pretty good and ran great. I showed it to some friends and one of them said "cool idea but I really like the look of all that stuff moving around". Hmm. He was right.
I was almost ready for paint when I decided to dismantle the whole thing and make it chain drive. That'll give it some moving parts. I spent hours on TinkerCAD designing a chain drive. It got complicated really quickly. On the On30 Shay the DC motor is mounted vertically with half of it and the gear box hanging below the chassis. This didn't leave any room for the chain drive so I had to change the motor position. With the motor laying horizontally I had more room underneath but I lost a lot of room inside the hoods where all the other components go. I had to completely reorganize everything and this is where a CAD program comes in really handy. I drew up the chassis with the chain drive hanging underneath and positioned the motor above it. I made boxes with dimensions matching speakers, the sound board, the RF receiver and the batteries. I used transparent boxes to show me the internal dimensions of the hoods and cab. I was able to choose the best speaker based on size and specs. In fact, in the end I had enough room for two speakers which should give more appropriate sound for the two Caterpillar engines. I also found batteries that would work better size-wise than my original choice.
So, once again, my project has snowballed. I think the chain drive will work well and if not I can always go back to the cheesy little transfer case idea. Learning to use TinkerCAD for finding room for everything was a big deal and if I ever go down this rabbit hole again I'll be sure to use it to help make my choices for components. As for now I'm waiting for parts to be delivered. More later.
Turntable Pt 5 - Arduino Sketch
This is an article I wrote for a book, "Arduino Intermediate Model Railroad Projects" by Paul and David Bradt. The book is available at Amazon (click here) or from the link on this blogs main page. The article provides a line-by-line copy of the sketch for operating a turntable using Arduino plus a complete description of how it works with suggestions of changes you could make to personalize it. In order to copy the sketch you'll have to remove the line numbers before copying over to Arduino. Hopefully before too long I'll figure out how to include the original file here.
7.3 Turn Table Project
By: Tom Ward
Description:
The Arduino sketch for this turntable project is a perfect example of how anyone can come up with an idea and get the help they need to build the code to make it happen. This is what is so cool about Arduino. It's fairly simple to understand and if the developer has trouble with a new concept there are always generous people available on the internet to guide you towards a solution. The authors and contributors of this book have tried to capture some of the challenges and ways to work around them too.
This project started with a concept and an idea of how the turntable should operate. The creator had never used any of the components (keypad, display, stepper motor, thumbstick) but realized there had to be a way to get everything working together. Searching the internet for sketches that used some of the key components found one sketch that used the keypad, LCD display and a stepper motor to operate a miter box for making precision cuts.
There was enough information on this website (https://www.brainy-bits.com) to learn how to program these different components. There was some difficulty making the change from linear to circular motion for this project. The Yahoo group called "Arduino for Model Railroad" provided the help needed for that conversion. The website is: (https://groups.yahoo.com/neo/groups/Arduini/info).
Two people, Dave Instone and David Harris, were instrumental in making the sketch come together but the whole group chimed in with thoughts and ideas. The online discussion continued for about two months developing this sketch and it's something that can be used by anyone looking for an easy and complete way to automate their own turntable. The following paragraphs cover the hardware and then the operation of the sketch.
For more information on this project please visit this website:
https://slimgauge.blogspot.com/p/for-actual-operation-of-turntable-i.html
Materials:
The material needed for this turntable control system is:
Arduino Mega 2560
SparkFun EasyDriver
Nokia 5110 LCD
4x4 matrix keypad
400 step NEMA 17 stepper motor
"thumbstick" style joystick
IR Break Beam detector
2 switches
Some LEDs.
The developer may be able to use an Arduino Uno but there are a large number of connections for this sketch.
Other components could be changed out but would require modifying the sketch.
A 200 step stepper motor can be substituted but the sketch would need to be modified and, more importantly, the operation wouldn't be as silky smooth.
Total cost of this control system, including the stepper motor, came to about $85.
Power Requirements:
The Mega and the EasyDriver both run on 5VDC and the stepper motor runs on 12VDC through the EasyDriver. The Mega provides power for the Keypad and the LCD display. "Wall-wart" style power supplies rated at 5VDC/1 amp and 12VDC/3 amp were used for this porject. There are quite a few connections to make but most of them are straightforward and all of them are listed in the beginning of the sketch (lines 9 - 37). "Comments" included in the sketch should provide enough information for most applications.
Challenges:
There are a couple of important things to note about the SparkFun EasyDriver. First, it can be programmed to run in different step modes, including full step, 1/2 step, 1/4 step and 1/8 step. This means that every full step gets broken down into multiple steps for smoother operation. In this project 1/8 step mode is used in the sketch but there are instances when that changes. Another benefit of using the EasyDriver is that it uses "AccelStepper" which is a software library for stepper motors. More on that later.
The 4x4 matrix keypad connections (lines 61 - 69) were a big challenge but understanding the pin out arrangement makes it easier to decipher. Making the physical connections and watching the LCD display made it easier too. The keypad has eight pins; four columns across the bottom and four rows down the side. Each button is assigned a column and row by its location on the keypad. Not all the keypads are pinned out the same because of differences in the way the traces are run on the board. Making a drawing of the keypad and the ribbon cable connector and then drawing lines to each column and row helps to understand how the pins are numbered and connected. The developer found out that it was just the opposite of what he thought it should be . The pin numbering was upside down and backwards and he corrected the problem by changing the connections at the Mega while watching the display. Some really inexpensive ($1.50) keypads have a removable paper covering which when removed allows the actual traces to be seen.
The Nokia LCD display is interesting. It was originally used in an older style cell phone. The display is 84 x 48 which gives enough room to show multiple lines of information. There is a lot of information about these on the internet. This site proved to be the most useful: (https://www.youtube.com/watch?v=FqJYb7wYAi8).
The "Brainy Bits" website (https://www.brainy-bits.com) is full of useful information with excellent explanations for the parts used in this controller. If a different display is used then a unique one can be designed by using Photoshop and then transfer it to an app called "LCD Assistant" that will do all the work to convert the image to the new LCD display. On this project things were kept simple and an existing display was modified and is shown in the code in lines 348 - 366.
Calculations:
1) The stepper motor uses 400 steps to make a full rotation. It has a 20 tooth M2 pulley mounted to the motor shaft. This is for a metric belt that has one tooth every 2mm. The belt connects to a 60 tooth M2 pulley mounted on the turntable shaft. This provides a gear reduction of 3:1. One full turn of the turntable requires 1200 steps. In 1/8 step mode it requires 9600 steps. This gives very smooth operation.
2) Knowing that there are 1200 full steps in one rotation, the distance between each step can be calculated which helps when setting up the tracks around the turntable pit. The developer’s turntable pit is 14.5" in diameter. Multiply that times pi (3.14) to get the circumference, 45.53". Now divide that by 1200 to get 0.038" and this is the distance between each full step at the wall of the pit. Then calculate the minimum distance between tracks and how many full steps are needed to go from one track to the next. This is very important data to know. The developer’s layout is in On30 scale so he needed a minimum of 1.1" between track centers to clear the ends of the ties. This allowed for up to 41 tracks around the pit although he only needed 16 tracks for his layout.
Operation:
When power is first applied to the turntable controls, the sketch is initiated and the stepper begins homing CCW in full step mode. An Infra-Red Beam Break detector was installed under the turntable platform. As the turntable bridge rotates it also rotates a small metal flag attached to the shaft beneath the layout. When the flag interrupts the IR beam it sends a signal to the Mega board which stops the stepper, sets that point as zero and turns on an LED to show it's been set. Everything the stepper does from that point on is referenced to that location. In this example there are 16 tracks around the turntable pit and each track is a certain number of steps from the zero point. They're listed in full steps in the program and that's how the stepper knows where to find a specific track. The operator can punch in a "2" on the keypad, hit the # key to enter it and the bridge/stepper knows to turn 90 steps to get to that track. If the operator enters 15 it'll go 975 steps. That's full steps though. The program knows that after the zero point is established it needs to multiply everything by 8 so that 975 steps now becomes 7800. That's how it operates so smoothly. The EasyDriver also uses code that automatically starts and ends every motion by slowly ramping up speed at the beginning and then ramping down to a stop. This creates a very realistic motion for the bridge whether it's based on an "Armstrong" (manual) or motor driven turntable.
Prototype turntables were used to position locomotives, to turn them so they'd be headed in the right direction for whatever job they had next. Sometimes an engine would come onto the turntable so it could be swung around 180 degrees and head right back out. To simulate this the operator enters the track number on the keypad and then enters "A" and the program knows to add 600 full steps or 4800 1/8 steps to the track value. If an engine comes onto the turntable bridge at track #15 the operator enters 15A on the keypad and the engine will be turned 180 degrees. It can then go back out track #15 headed in the opposite direction.
One key lesson learned is that it’s important to know one end of the bridge from the other. Prototype motorized bridges might have an operators shack at one end. The armstrong bridge has a wooden pushbar at each end and the developer painted the tip of one of these white for easy identification. A cool provision in the program is for automatically deciding which direction to turn. If the engine enters the bridge at track #2 and it is desired to exit at track #15 the program automatically decides if it should turn CW or CCW for the shortest distance to get there. If it has to turn CCW past the Zero location it will keep track in negative steps of how far past it went.
The LCD screen is set up to display current track #, next track # and it also displays "mvng" (moving) when the bridge is in motion. There is also a part of the program set up for an emergency stop which would be initiated by hitting a switch on the control panel. There's an LED for display of the emergency stop condition.
By entering "C" on the keypad it enters thumbstick mode. The display changes to give a constant step readout and depending on how far the thumbstick is pushed the speed will ramp up through four different speeds. Operation is in full step mode. The developer set it up this way because the thumbstick would only be used to help add a new track location. Step the bridge to where the new track is located and the display will give the full step number needed to be added to the program. This thumbstick may not be used often but it is available if needed. Enter "D" to return to normal sketch operation.
In the sketch the operator can enter the location of the tracks by modifying the full step numbers in the "long steps[NUMTRACKS] =" command on line 86. Note that they start with 0 so there are 16 locations for this example, 0 - 15. This can be changed on line 85 by modifying the number of tracks needed. Other easy changes are speed and acceleration of the stepper motor on lines 125 and 126 as well as several other areas of the sketch. Adjust the backlight brightness of the LCD on line 95.
This sketch is fairly complex with over 500 lines of code but it is "commented" throughout and fairly easy to understand. It's laid out in "void" control sections. Void Loop accesses these when needed to perform different functions:
"void start TT" (lines 270 - 286) is all about moving the turntable and updating the display.
"void setMicrosteps" (lines 291 - 343) is for selecting step mode and calculating position.
"void drawnokiascreen" (lines 348 - 366) is for updating the display. The second one, "void drawnokiascreen2" is for the display while in "thumbstick" mode.
"void Joystick" (lines 428 - 507) is the control of the thumbstick. Changes here are for sensitivity of the speed control in the "switch" function by adjusting the length of the "case" numbers. The full range is 0 to 512 and it is currently set up for four speeds. This section of the sketch was eliminated for the printed version of this book. The full sketch can be downloaded here ().
There is a section (lines 392 - 425) titled "shortest path". This is the code that decides what direction to drive the bridge to get to it's next location in the shortest number of steps.
"char checkKB()" (lines 218 - 266) assigns the keys for the keypad. Note that the "*" (star) key is used to erase an entry, basically a backspace key. The "#" (pound) key is the enter button. The "A" key is used to enter a 180 degree bridge turn. The "B" key is not currently programmed. The "C" key selects "thumbstick" mode and the "D" key is used to return from "thumbstick" mode to normal operation.
"void setup" (lines 92 - 165) is used to initialize the LCD screen, assign pins on the Mega and set the speed and acceleration of the stepper motor. This is where the bridge is initially run to set the Zero point.
Below is an incomplete listing of the turntable sketch:
1 // Model railroad turntable indexing control
2 // Created by Dave Instone and Tom Ward
3
4 #include <AccelStepper.h> // AccelStepper Library
5 #include <Keypad.h> // Keypad Library
6 #include "U8glib.h" // U8glib for Nokia LCD
7 #include <Wire.h>
8
9 //===============Pin Asignments===================
10 #define StepperEnable 2 // Arduino pin 2 to EasyDriver Enable
11 #define home_switch 9 // Arduino pin 9 to Home Switch (IR Beam Break)
12 #define EmergStop 10 // Arduino pin 10 to Emergency stop switch
13 #define EmergStop_led 12 // When lit indicates Emergency Stop activated, program stopped
14
15 //================EasyDriver Pins=================
16 #define sleep_pin 39 // Arduino pin 39 to EasyDriver Sleep pin
17 #define MS1 41 // Arduino pin 41 to EasyDriver MS1
18 #define MS2 43 // Arduino pin 43 to EasyDriver MS2
19 #define step_pin A0 // Arduino pin A0 to EasyDriver Steps pin
20 #define dir_pin A1 // Arduino pin A1 to EasyDriver Direction pin
21
22 //==================Joystick======================
23 #define Joy_switch 45 // Pin 45 connected to joystick switch - not used
24 #define x_pin A2 // Arduino pin A2 to joystick x axis pin
25 #define manual_mode_led 45 // When lit indicates thumb stick control
26
27 #define home_led 8 // When lit indicates stepper is home
28
29 //==================Nokia Pins====================
30 #define backlight_pin 11
31 #define UG_CLK 3
32 #define UG_DIN 4
33 #define UG_CE 6
34 #define UG_DC 5
35 #define UG_RST 7
36
37 // Note: Keypad pins assigned in keypad init.
38
39 //===============Keypad Variables=================
40 int enteredTrack = 0; // used for track entry
41 int targetTrack; // goal of a move
42 bool reversed = false; // selects end of TT to align with exit
43
44 //=================Display Strings================
45 String sCurrentPosition;
46 String sTargetTrack;
47 String sEnteredTrack;
48 String sStepCount;
49
50 //==========Miscellaneous Variables===============
51 int microStepsPerFullStep;
52 byte enable = LOW; // the stepper is enabled when StepperEnable is low or 0
53 long initial_homing; // Used to Home Stepper at startup
54 int step_speed = 30; // Speed of Stepper motor (higher = slower) in JS mode
55
56 //=================Constants=====================
57 const long basicStepsPerRev = 1200; // set by the mechanics of the TT drive
58
59 //===========Library Initialisations=============
60 //===Keypad===
61 const byte ROWS = 4; // Four Rows
62 const byte COLS = 4; // Four Columns
63 byte rowPins[ROWS] = {22, 24, 26, 28}; // Arduino pins connected to the row pins of the keypad
64 byte colPins[COLS] = {31, 33, 35, 37}; // Arduino pins connected to the column pins of the keypad
65 char keys[ROWS][COLS] = {
66 {'1', '2', '3', 'A'},
67 {'4', '5', '6', 'B'},
68 {'7', '8', '9', 'C'},
69 {'*', '0', '#', 'D'}
70 };
71 Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Keypad Library definition
72
73 //===U8glib Setup for Nokia LCD===
74 U8GLIB_PCD8544 u8g(UG_CLK,UG_DIN,UG_CE,UG_DC,UG_RST);
75 // CLK=3, DIN=4, CE=6, DC=5, RST=7
76
77 //===AccelStepper Setup===
78 AccelStepper stepper(1, step_pin, dir_pin); // 1 selects Easy Driver interface
79
80 //===Stepper Step Settings for Each Exit===
81 /*
82 0 is furthest CCW exit and is always 0, for 1, 2, 3, etc substitute the actual
83 // number of full steps to that exit from the furthest CCW exit
84 */
85 #define NUMTRACKS 16
86 long steps[NUMTRACKS] = {0, 60, 90, 120, 180, 240, 270, 300, 330, 375, 405, 435, 465, 600, 765, 975};
87 // For info only: 1/8 = {0, 480, 720, 960, 1440, 1920, 2160, 2400, 2640, 3000, 3240, 3440, 3720, 4800, 6120, 7800}
88
89
90 //=======================================================
91
92 void setup(void) {
93
94 // Light up the LCD backlight LEDS
95 analogWrite(backlight_pin, 255); // Set the Backlight intensity (0=Bright, 255=Dim)
96
97 // Draw initialise variables for Nokia LCD and draw initial screen
98 sCurrentPosition = "";
99 sStepCount = "";
100 sTargetTrack = "";
101 sEnteredTrack = "";
102 drawnokiascreen1(); // Display update for Keypad mode
103 drawnokiascreen2(); // Display update for Joystick mode
104
105 // Set pin directions
106 pinMode(StepperEnable, OUTPUT);
107 pinMode(MS1, OUTPUT);
108 pinMode(MS2, OUTPUT);
109 pinMode(home_switch, INPUT_PULLUP);
110 pinMode(x_pin, INPUT_PULLUP);
111 pinMode(dir_pin, OUTPUT);
112 pinMode(step_pin, OUTPUT);
113 pinMode(home_led, OUTPUT);
114 pinMode(EmergStop, INPUT_PULLUP);
115 pinMode(sleep_pin, OUTPUT);
116 pinMode(EmergStop_led, OUTPUT);
117 pinMode(manual_mode_led, OUTPUT);
118 pinMode(Joy_switch, INPUT_PULLUP);
119
120 // Start Homing procedure of Stepper Motor at startup
121 delay(5); // Wait for EasyDriver wake up
122 digitalWrite(sleep_pin, HIGH);
123
124 // AccelStepper speed and acceleration setup for homing
125 stepper.setMaxSpeed(25); // Not too fast or you will have missed steps
126 stepper.setAcceleration(10); // Too fast here can also cause missed steps
127 // Set EasyDriver MS1 & 2 for homing and preset microstepsperfullstep
128 microStepsPerFullStep = 1; // need to initialise with 1 so that setMicrosteps() is OK
129 setMicrosteps(1); // Set MS1 & 2 for full steps, only for homing
130 initial_homing = -1;
131 digitalWrite(StepperEnable, enable); //enable stepper drive outputs
132 while (digitalRead(home_switch)) { // Make the Stepper move CCW until the switch is activated
133 stepper.moveTo(initial_homing); // Set the position to move to
134 initial_homing--; // Decrease by 1 for next move if needed
135 stepper.run(); // Start moving the stepper
136 delay(5);
137 }
138
139 initial_homing = 1;
140
141 while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
142 stepper.moveTo(initial_homing);
143 stepper.run();
144 initial_homing++;
145 delay(5);
146 }
147 // Zero AccelStepper
148 stepper.setCurrentPosition(steps[0]);
149
150 digitalWrite(home_led, HIGH); //Turn on the LED
151 targetTrack = 0;
152 enteredTrack = 0;
153 sCurrentPosition = sTargetTrack; // Change to string for display
154 sStepCount = String(stepper.currentPosition());
155 sEnteredTrack = "";
156 drawnokiascreen1(); // Update display
157
158 digitalWrite(sleep_pin, HIGH);
159
160 // Set operational speeds and microsteps
161 setMicrosteps(8); // Set 1/8 steps
162 stepper.setMaxSpeed(100.0); // Set Max Speed of Stepper (Faster for regular movements)
163 stepper.setAcceleration(25.0); // Set Acceleration of Stepper
164
165 }
166
167 //====================================================
168
169 void loop() {
170 long newStepCount;
171 static long lastStepCount = 0;
172 static boolean once = false;
173 static bool estop = false;
174 // The above only get executed once however many times the loop runs
175
176 if (checkKB() == '#') {
177 digitalWrite(StepperEnable, enable);
178 startTT();
179 once = true; // Update the screen only once at end of movement
180 estop = false; // Reset estop flag
181 }
182 if (stepper.distanceToGo() != 0) { // The motor still needs to run
183 stepper.run(); // Not at exit yet
184 newStepCount = stepper.currentPosition();
185 if (newStepCount!=lastStepCount){ // Only print if it's changed
186 lastStepCount = newStepCount;
187 if (newStepCount % 48 == 0){ // Only every 48 steps, more often interferes with operation
188 sStepCount = String(newStepCount);
189 lastStepCount = newStepCount;
190 drawnokiascreen1(); // Update display
191 }
192 }
193 // Check for emergency stop pressed
194 if ( !digitalRead(EmergStop) && !estop ) {
195
196 // Now tell software to stop motor, but only once so set estop flag
197 stepper.stop(); // Tell software to stop motor
198 estop = true;
199 digitalWrite(EmergStop_led, HIGH); // Turn on emergency stop LED
200 }
201 }
202 if (stepper.distanceToGo() == 0) { // The motor is stopped but has it just stopped?
203 if (once) { // Just stopped so update the display and reset reversed once and estop
204 sCurrentPosition = sTargetTrack; // Change to string for display
205 sStepCount = String(stepper.currentPosition()); // Adds steps to display at end of move
206 sEnteredTrack = "";
207 drawnokiascreen1(); // Update display
208 reversed = false; // Reset reversed etc
209 once = false;
210 estop = false;
211 }
212 }
213
214 }
215
216 //====================================================
217
218 char checkKB() {
219 char keypressed;
220 keypressed = keypad.getKey();
221 switch (keypressed) {
222 case NO_KEY :
223 break; // Nothing to do
224 case '#': // Start TT moving
225 return keypressed;
226 break;
227 case 'A' :
228 reversed = !reversed;
229 sTargetTrack = String(enteredTrack); // Change to string for display
230 if ( reversed ) {
231 sTargetTrack = String(-enteredTrack); // Indicate reversed for display
232 }
233 sEnteredTrack = sTargetTrack;
234 drawnokiascreen1(); // Update display
235 break;
236 case '*' :
237 enteredTrack = 0;
238 sEnteredTrack = "";
239 drawnokiascreen1(); // Update display
240 break;
241 case '0' ... '9' :
242 enteredTrack = (enteredTrack * 10) + (keypressed - '0');
243 // Converts keypressed to integer and builds multidigit number
244 if (enteredTrack > NUMTRACKS) {
245 enteredTrack = NUMTRACKS; // Not past the last track
246 }
247 sTargetTrack = String(enteredTrack);
248 if ( reversed )
249 sTargetTrack = String(-targetTrack); // Indicate reversed
250 sEnteredTrack = sTargetTrack;
251 drawnokiascreen1(); // Update display
252 break;
253 case 'B':
254 // Do code here but better to return 'B';
255 // And call a function or call the function here
256 break;
257 case 'C':
258 JoyStick(1);
259 break;
260 case 'D':
261 //
262 break;
263
264 } // End of switch
265 return ' ';
266 }
267
268 //====================================================
269
270 void startTT() {
271
272 stepper.moveTo(calcSteps(enteredTrack, basicStepsPerRev , microStepsPerFullStep, reversed));
273 // Go to new position
274
275 sCurrentPosition = String("mvng"); // Indicate a move is in progress
276
277 targetTrack = enteredTrack; // Remember targetTrack
278 sTargetTrack = String(targetTrack); // Change to string for display
279 if ( reversed ) {
280 sTargetTrack = String(-targetTrack); // Indicate reversed for display
281 }
282 enteredTrack = 0; // Prepare for next track input
283 sStepCount = String(stepper.currentPosition());
284 sEnteredTrack = sTargetTrack;
285 drawnokiascreen1(); // Update display
286 }
287
288
289 //====================================================
290
291 void setMicrosteps(int stepsPer) {
292 /*
293 Configure MS1 & 2 of easydriver and also set
294 value of microStepsPerFullStep to the corresponding value
295 and update Accelstepper current position in terms of
296 new step setting.
297 When reducing number of micro steps rounding errors can
298 cause step alignment errors.
299 If decreasing microsteps check if
300 stepper.currentPosition() MOD current microsteps is zero
301 If not move the stepper in steps until it is
302 */
303 switch (stepsPer) {
304 case 1 :
305 digitalWrite(MS1, 0); // (1) Full Step
306 digitalWrite(MS2, 0);
307 break;
308 case 2:
309 digitalWrite(MS1, 1); // (2) Half Step
310 digitalWrite(MS2, 0);
311 break;
312 case 4 :
313 digitalWrite(MS1, 0); // (4) Quarter Step
314 digitalWrite(MS2, 1);
315 break;
316 case 8:
317 digitalWrite(MS1, 1); // (8) Eighth Step
318 digitalWrite(MS2, 1);
319 break;
320 default: // Default is 8 microsteps
321 digitalWrite(MS1, 1);
322 digitalWrite(MS2, 1);
323 stepsPer = 8;
324 }
325 if (stepsPer == microStepsPerFullStep) {
326 microStepsPerFullStep = stepsPer;
327 return;
328 } // Handles initial setup the very first time called
329
330 // Check for non MOD = 0 current position
331 int oddsteps = stepper.currentPosition() % microStepsPerFullStep;
332 if ((stepsPer < microStepsPerFullStep) && (oddsteps != 0)) {
333 // Need to move until oddsteps is zero
334 stepper.move(microStepsPerFullStep - oddsteps); // Relative move
335 stepper.runToPosition(); // Does the move
336 }
337 // Now adjust for new step setting
338 long currentSteps = stepper.currentPosition(); // Read current position
339 currentSteps = currentSteps * stepsPer; // Multiply by new setting
340 currentSteps = (currentSteps / microStepsPerFullStep); // And divide by the old
341 stepper.setCurrentPosition(currentSteps); // And write it back
342 microStepsPerFullStep = stepsPer; // Save new setting
343 }
344
345
346 //===================================================
347
348 void drawnokiascreen1() { // Screen display #1
349 u8g.firstPage();
350 do {
351 u8g.drawHLine(0, 15, 84); // Draw top horizontal line
352 u8g.drawVLine(50, 0, 47); // Draw vertical line
353 u8g.drawHLine(0, 35, 84); // Draw bottom horizontal line
354 u8g.setFont(u8g_font_profont11); // Set font
355 u8g.drawStr(4, 10, "cur-pos");
356 u8g.setPrintPos(57, 14);
357 u8g.print(sCurrentPosition); // Display current position
358 u8g.drawStr(4, 29, "step #");
359 u8g.setPrintPos(57, 29);
360 u8g.print(sStepCount); // Display current step count of stepper
361 u8g.drawStr(4, 46, "new-pos");
362 u8g.setPrintPos(57, 47);
363 u8g.print(sEnteredTrack); // Display new track #
364 }
365 while ( u8g.nextPage() );
366 }
367
368 //====================================================
369
370 void drawnokiascreen2() { // Screen display #2
371 u8g.firstPage();
372 do {
373 u8g.drawHLine(0, 15, 84);
374 u8g.drawVLine(50, 15, 47);
375 u8g.drawHLine(0, 35, 84);
376 u8g.setFont(u8g_font_profont11);
377 u8g.drawStr(4, 10, "joystick mode"); // Display "Joystick Mode"
378 u8g.setPrintPos(57, 14);
379 u8g.print(sCurrentPosition); // No display here in Joystick mode
380 u8g.drawStr(4, 29, "step #");
381 u8g.setPrintPos(57, 29);
382 u8g.print(sStepCount); // Display step count of stepper
383 u8g.drawStr(4, 46, "stp-spd");
384 u8g.setPrintPos(57, 47);
385 u8g.print(sEnteredTrack); // Display step speed of stepper
386 }
387 while ( u8g.nextPage() );
388 }
389
390 //====================================================
391
392 // Shortest path to new track
393
394 long calcSteps(int destination, long FullstepsPerRev, long microSteps, boolean alignReversedEnd) {
395 long microStepsPerRev = FullstepsPerRev * microSteps;
396 long stepsFor180 = microStepsPerRev / 2;
397
398 // Read current position and transfor into the range 0 to microStepsPerRev
399 long currentSteps = stepper.currentPosition();
400
401 currentSteps = currentSteps % microStepsPerRev; // Reduce below steps /rev
402 if (currentSteps < 0) currentSteps = currentSteps + microStepsPerRev; // Make -ve's +ve
403
404 // Update AccelStepper with the 0 to microStepsPerRev range position
405 stepper.setCurrentPosition(currentSteps);
406
407 // Now get the steps for the new destination and add 1/2 rev if reversed
408 long newSteps = steps[destination]* microSteps;
409 if (alignReversedEnd) {
410 newSteps += stepsFor180;
411 newSteps = newSteps % microStepsPerRev; // No point in doing more than 1 rev!!
412 }
413 // If less than or equal to a half rev we are done
414 if (abs(newSteps - currentSteps) <= stepsFor180) return newSteps; // EXIT all done
415
416 // If we are here the number of steps is more than stepsFor180 so we need to reverse
417 //direction from the 'norm'
418 if (newSteps < currentSteps) {
419 // Convert CCW to CW
420 return newSteps += microStepsPerRev; //EXIT
421 } else {
422 // Convert CW to CCW
423 return newSteps -= microStepsPerRev; //EXIT
424 }
425 }
426 //====================================================
427
428 void JoyStick(int Microsteps) {
Summary:
Note: The full version of this sketch can be downloaded through the MRH-rrworks-collab.io website and requires membership which is not complicated. Follow this link (click here). Please note that this sketch is copyrighted and not intended for sale or distribution. Intended only for individual use.
The turntable can be the center of attention and operation for your engine facility. Manually controlling the bridge with a hand-wheel and gear connection is a quick and easy way to get things in operation but there's a better way and it doesn't cost an arm and a leg. In fact, the cost is comparable to setting up a hand crank with gear reduction and u-joints. Maybe the only real disadvantage to manual control is that you have to be able to clearly see the bridge location to get the tracks lined up. This sketch and associated parts were developed because the turntable is located over 2' from where the operator stands and his vision isn't what it used to be. This is the perfect application for a stepper motor. It's accurate and stops are repeatable. Motion can be programmed to suit your eye. The motion is really the star here because it's realistically smooth and slow and that ramp-up and ramp-down of speed is the cat's meow. Another advantage to remote Arduino operation is that you can quickly punch in your command and then just observe as the turntable goes through it's operation just like there were two 1.5" tall guys in dirty blue overalls leaning into those push-bars.
This sketch was designed for easy operation. Most of it is intuitive and the explanation of code throughout makes for easy-to-understand commands. It doesn't take long before you're going through the sketch and modifying things for your own application. And then once you have all of your track locations added in it's just a matter of deciding where you want to go, entering a number and enjoying the show.
7.3 Turn Table Project
By: Tom Ward
Description:
The Arduino sketch for this turntable project is a perfect example of how anyone can come up with an idea and get the help they need to build the code to make it happen. This is what is so cool about Arduino. It's fairly simple to understand and if the developer has trouble with a new concept there are always generous people available on the internet to guide you towards a solution. The authors and contributors of this book have tried to capture some of the challenges and ways to work around them too.
This project started with a concept and an idea of how the turntable should operate. The creator had never used any of the components (keypad, display, stepper motor, thumbstick) but realized there had to be a way to get everything working together. Searching the internet for sketches that used some of the key components found one sketch that used the keypad, LCD display and a stepper motor to operate a miter box for making precision cuts.
There was enough information on this website (https://www.brainy-bits.com) to learn how to program these different components. There was some difficulty making the change from linear to circular motion for this project. The Yahoo group called "Arduino for Model Railroad" provided the help needed for that conversion. The website is: (https://groups.yahoo.com/neo/groups/Arduini/info).
Two people, Dave Instone and David Harris, were instrumental in making the sketch come together but the whole group chimed in with thoughts and ideas. The online discussion continued for about two months developing this sketch and it's something that can be used by anyone looking for an easy and complete way to automate their own turntable. The following paragraphs cover the hardware and then the operation of the sketch.
For more information on this project please visit this website:
https://slimgauge.blogspot.com/p/for-actual-operation-of-turntable-i.html
Materials:
The material needed for this turntable control system is:
Arduino Mega 2560
SparkFun EasyDriver
Nokia 5110 LCD
4x4 matrix keypad
400 step NEMA 17 stepper motor
"thumbstick" style joystick
IR Break Beam detector
2 switches
Some LEDs.
The developer may be able to use an Arduino Uno but there are a large number of connections for this sketch.
Other components could be changed out but would require modifying the sketch.
A 200 step stepper motor can be substituted but the sketch would need to be modified and, more importantly, the operation wouldn't be as silky smooth.
Total cost of this control system, including the stepper motor, came to about $85.
Power Requirements:
The Mega and the EasyDriver both run on 5VDC and the stepper motor runs on 12VDC through the EasyDriver. The Mega provides power for the Keypad and the LCD display. "Wall-wart" style power supplies rated at 5VDC/1 amp and 12VDC/3 amp were used for this porject. There are quite a few connections to make but most of them are straightforward and all of them are listed in the beginning of the sketch (lines 9 - 37). "Comments" included in the sketch should provide enough information for most applications.
Challenges:
There are a couple of important things to note about the SparkFun EasyDriver. First, it can be programmed to run in different step modes, including full step, 1/2 step, 1/4 step and 1/8 step. This means that every full step gets broken down into multiple steps for smoother operation. In this project 1/8 step mode is used in the sketch but there are instances when that changes. Another benefit of using the EasyDriver is that it uses "AccelStepper" which is a software library for stepper motors. More on that later.
The 4x4 matrix keypad connections (lines 61 - 69) were a big challenge but understanding the pin out arrangement makes it easier to decipher. Making the physical connections and watching the LCD display made it easier too. The keypad has eight pins; four columns across the bottom and four rows down the side. Each button is assigned a column and row by its location on the keypad. Not all the keypads are pinned out the same because of differences in the way the traces are run on the board. Making a drawing of the keypad and the ribbon cable connector and then drawing lines to each column and row helps to understand how the pins are numbered and connected. The developer found out that it was just the opposite of what he thought it should be . The pin numbering was upside down and backwards and he corrected the problem by changing the connections at the Mega while watching the display. Some really inexpensive ($1.50) keypads have a removable paper covering which when removed allows the actual traces to be seen.
The Nokia LCD display is interesting. It was originally used in an older style cell phone. The display is 84 x 48 which gives enough room to show multiple lines of information. There is a lot of information about these on the internet. This site proved to be the most useful: (https://www.youtube.com/watch?v=FqJYb7wYAi8).
The "Brainy Bits" website (https://www.brainy-bits.com) is full of useful information with excellent explanations for the parts used in this controller. If a different display is used then a unique one can be designed by using Photoshop and then transfer it to an app called "LCD Assistant" that will do all the work to convert the image to the new LCD display. On this project things were kept simple and an existing display was modified and is shown in the code in lines 348 - 366.
Calculations:
1) The stepper motor uses 400 steps to make a full rotation. It has a 20 tooth M2 pulley mounted to the motor shaft. This is for a metric belt that has one tooth every 2mm. The belt connects to a 60 tooth M2 pulley mounted on the turntable shaft. This provides a gear reduction of 3:1. One full turn of the turntable requires 1200 steps. In 1/8 step mode it requires 9600 steps. This gives very smooth operation.
2) Knowing that there are 1200 full steps in one rotation, the distance between each step can be calculated which helps when setting up the tracks around the turntable pit. The developer’s turntable pit is 14.5" in diameter. Multiply that times pi (3.14) to get the circumference, 45.53". Now divide that by 1200 to get 0.038" and this is the distance between each full step at the wall of the pit. Then calculate the minimum distance between tracks and how many full steps are needed to go from one track to the next. This is very important data to know. The developer’s layout is in On30 scale so he needed a minimum of 1.1" between track centers to clear the ends of the ties. This allowed for up to 41 tracks around the pit although he only needed 16 tracks for his layout.
Operation:
When power is first applied to the turntable controls, the sketch is initiated and the stepper begins homing CCW in full step mode. An Infra-Red Beam Break detector was installed under the turntable platform. As the turntable bridge rotates it also rotates a small metal flag attached to the shaft beneath the layout. When the flag interrupts the IR beam it sends a signal to the Mega board which stops the stepper, sets that point as zero and turns on an LED to show it's been set. Everything the stepper does from that point on is referenced to that location. In this example there are 16 tracks around the turntable pit and each track is a certain number of steps from the zero point. They're listed in full steps in the program and that's how the stepper knows where to find a specific track. The operator can punch in a "2" on the keypad, hit the # key to enter it and the bridge/stepper knows to turn 90 steps to get to that track. If the operator enters 15 it'll go 975 steps. That's full steps though. The program knows that after the zero point is established it needs to multiply everything by 8 so that 975 steps now becomes 7800. That's how it operates so smoothly. The EasyDriver also uses code that automatically starts and ends every motion by slowly ramping up speed at the beginning and then ramping down to a stop. This creates a very realistic motion for the bridge whether it's based on an "Armstrong" (manual) or motor driven turntable.
Prototype turntables were used to position locomotives, to turn them so they'd be headed in the right direction for whatever job they had next. Sometimes an engine would come onto the turntable so it could be swung around 180 degrees and head right back out. To simulate this the operator enters the track number on the keypad and then enters "A" and the program knows to add 600 full steps or 4800 1/8 steps to the track value. If an engine comes onto the turntable bridge at track #15 the operator enters 15A on the keypad and the engine will be turned 180 degrees. It can then go back out track #15 headed in the opposite direction.
One key lesson learned is that it’s important to know one end of the bridge from the other. Prototype motorized bridges might have an operators shack at one end. The armstrong bridge has a wooden pushbar at each end and the developer painted the tip of one of these white for easy identification. A cool provision in the program is for automatically deciding which direction to turn. If the engine enters the bridge at track #2 and it is desired to exit at track #15 the program automatically decides if it should turn CW or CCW for the shortest distance to get there. If it has to turn CCW past the Zero location it will keep track in negative steps of how far past it went.
The LCD screen is set up to display current track #, next track # and it also displays "mvng" (moving) when the bridge is in motion. There is also a part of the program set up for an emergency stop which would be initiated by hitting a switch on the control panel. There's an LED for display of the emergency stop condition.
By entering "C" on the keypad it enters thumbstick mode. The display changes to give a constant step readout and depending on how far the thumbstick is pushed the speed will ramp up through four different speeds. Operation is in full step mode. The developer set it up this way because the thumbstick would only be used to help add a new track location. Step the bridge to where the new track is located and the display will give the full step number needed to be added to the program. This thumbstick may not be used often but it is available if needed. Enter "D" to return to normal sketch operation.
In the sketch the operator can enter the location of the tracks by modifying the full step numbers in the "long steps[NUMTRACKS] =" command on line 86. Note that they start with 0 so there are 16 locations for this example, 0 - 15. This can be changed on line 85 by modifying the number of tracks needed. Other easy changes are speed and acceleration of the stepper motor on lines 125 and 126 as well as several other areas of the sketch. Adjust the backlight brightness of the LCD on line 95.
This sketch is fairly complex with over 500 lines of code but it is "commented" throughout and fairly easy to understand. It's laid out in "void" control sections. Void Loop accesses these when needed to perform different functions:
"void start TT" (lines 270 - 286) is all about moving the turntable and updating the display.
"void setMicrosteps" (lines 291 - 343) is for selecting step mode and calculating position.
"void drawnokiascreen" (lines 348 - 366) is for updating the display. The second one, "void drawnokiascreen2" is for the display while in "thumbstick" mode.
"void Joystick" (lines 428 - 507) is the control of the thumbstick. Changes here are for sensitivity of the speed control in the "switch" function by adjusting the length of the "case" numbers. The full range is 0 to 512 and it is currently set up for four speeds. This section of the sketch was eliminated for the printed version of this book. The full sketch can be downloaded here ().
There is a section (lines 392 - 425) titled "shortest path". This is the code that decides what direction to drive the bridge to get to it's next location in the shortest number of steps.
"char checkKB()" (lines 218 - 266) assigns the keys for the keypad. Note that the "*" (star) key is used to erase an entry, basically a backspace key. The "#" (pound) key is the enter button. The "A" key is used to enter a 180 degree bridge turn. The "B" key is not currently programmed. The "C" key selects "thumbstick" mode and the "D" key is used to return from "thumbstick" mode to normal operation.
"void setup" (lines 92 - 165) is used to initialize the LCD screen, assign pins on the Mega and set the speed and acceleration of the stepper motor. This is where the bridge is initially run to set the Zero point.
Below is an incomplete listing of the turntable sketch:
1 // Model railroad turntable indexing control
2 // Created by Dave Instone and Tom Ward
3
4 #include <AccelStepper.h> // AccelStepper Library
5 #include <Keypad.h> // Keypad Library
6 #include "U8glib.h" // U8glib for Nokia LCD
7 #include <Wire.h>
8
9 //===============Pin Asignments===================
10 #define StepperEnable 2 // Arduino pin 2 to EasyDriver Enable
11 #define home_switch 9 // Arduino pin 9 to Home Switch (IR Beam Break)
12 #define EmergStop 10 // Arduino pin 10 to Emergency stop switch
13 #define EmergStop_led 12 // When lit indicates Emergency Stop activated, program stopped
14
15 //================EasyDriver Pins=================
16 #define sleep_pin 39 // Arduino pin 39 to EasyDriver Sleep pin
17 #define MS1 41 // Arduino pin 41 to EasyDriver MS1
18 #define MS2 43 // Arduino pin 43 to EasyDriver MS2
19 #define step_pin A0 // Arduino pin A0 to EasyDriver Steps pin
20 #define dir_pin A1 // Arduino pin A1 to EasyDriver Direction pin
21
22 //==================Joystick======================
23 #define Joy_switch 45 // Pin 45 connected to joystick switch - not used
24 #define x_pin A2 // Arduino pin A2 to joystick x axis pin
25 #define manual_mode_led 45 // When lit indicates thumb stick control
26
27 #define home_led 8 // When lit indicates stepper is home
28
29 //==================Nokia Pins====================
30 #define backlight_pin 11
31 #define UG_CLK 3
32 #define UG_DIN 4
33 #define UG_CE 6
34 #define UG_DC 5
35 #define UG_RST 7
36
37 // Note: Keypad pins assigned in keypad init.
38
39 //===============Keypad Variables=================
40 int enteredTrack = 0; // used for track entry
41 int targetTrack; // goal of a move
42 bool reversed = false; // selects end of TT to align with exit
43
44 //=================Display Strings================
45 String sCurrentPosition;
46 String sTargetTrack;
47 String sEnteredTrack;
48 String sStepCount;
49
50 //==========Miscellaneous Variables===============
51 int microStepsPerFullStep;
52 byte enable = LOW; // the stepper is enabled when StepperEnable is low or 0
53 long initial_homing; // Used to Home Stepper at startup
54 int step_speed = 30; // Speed of Stepper motor (higher = slower) in JS mode
55
56 //=================Constants=====================
57 const long basicStepsPerRev = 1200; // set by the mechanics of the TT drive
58
59 //===========Library Initialisations=============
60 //===Keypad===
61 const byte ROWS = 4; // Four Rows
62 const byte COLS = 4; // Four Columns
63 byte rowPins[ROWS] = {22, 24, 26, 28}; // Arduino pins connected to the row pins of the keypad
64 byte colPins[COLS] = {31, 33, 35, 37}; // Arduino pins connected to the column pins of the keypad
65 char keys[ROWS][COLS] = {
66 {'1', '2', '3', 'A'},
67 {'4', '5', '6', 'B'},
68 {'7', '8', '9', 'C'},
69 {'*', '0', '#', 'D'}
70 };
71 Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Keypad Library definition
72
73 //===U8glib Setup for Nokia LCD===
74 U8GLIB_PCD8544 u8g(UG_CLK,UG_DIN,UG_CE,UG_DC,UG_RST);
75 // CLK=3, DIN=4, CE=6, DC=5, RST=7
76
77 //===AccelStepper Setup===
78 AccelStepper stepper(1, step_pin, dir_pin); // 1 selects Easy Driver interface
79
80 //===Stepper Step Settings for Each Exit===
81 /*
82 0 is furthest CCW exit and is always 0, for 1, 2, 3, etc substitute the actual
83 // number of full steps to that exit from the furthest CCW exit
84 */
85 #define NUMTRACKS 16
86 long steps[NUMTRACKS] = {0, 60, 90, 120, 180, 240, 270, 300, 330, 375, 405, 435, 465, 600, 765, 975};
87 // For info only: 1/8 = {0, 480, 720, 960, 1440, 1920, 2160, 2400, 2640, 3000, 3240, 3440, 3720, 4800, 6120, 7800}
88
89
90 //=======================================================
91
92 void setup(void) {
93
94 // Light up the LCD backlight LEDS
95 analogWrite(backlight_pin, 255); // Set the Backlight intensity (0=Bright, 255=Dim)
96
97 // Draw initialise variables for Nokia LCD and draw initial screen
98 sCurrentPosition = "";
99 sStepCount = "";
100 sTargetTrack = "";
101 sEnteredTrack = "";
102 drawnokiascreen1(); // Display update for Keypad mode
103 drawnokiascreen2(); // Display update for Joystick mode
104
105 // Set pin directions
106 pinMode(StepperEnable, OUTPUT);
107 pinMode(MS1, OUTPUT);
108 pinMode(MS2, OUTPUT);
109 pinMode(home_switch, INPUT_PULLUP);
110 pinMode(x_pin, INPUT_PULLUP);
111 pinMode(dir_pin, OUTPUT);
112 pinMode(step_pin, OUTPUT);
113 pinMode(home_led, OUTPUT);
114 pinMode(EmergStop, INPUT_PULLUP);
115 pinMode(sleep_pin, OUTPUT);
116 pinMode(EmergStop_led, OUTPUT);
117 pinMode(manual_mode_led, OUTPUT);
118 pinMode(Joy_switch, INPUT_PULLUP);
119
120 // Start Homing procedure of Stepper Motor at startup
121 delay(5); // Wait for EasyDriver wake up
122 digitalWrite(sleep_pin, HIGH);
123
124 // AccelStepper speed and acceleration setup for homing
125 stepper.setMaxSpeed(25); // Not too fast or you will have missed steps
126 stepper.setAcceleration(10); // Too fast here can also cause missed steps
127 // Set EasyDriver MS1 & 2 for homing and preset microstepsperfullstep
128 microStepsPerFullStep = 1; // need to initialise with 1 so that setMicrosteps() is OK
129 setMicrosteps(1); // Set MS1 & 2 for full steps, only for homing
130 initial_homing = -1;
131 digitalWrite(StepperEnable, enable); //enable stepper drive outputs
132 while (digitalRead(home_switch)) { // Make the Stepper move CCW until the switch is activated
133 stepper.moveTo(initial_homing); // Set the position to move to
134 initial_homing--; // Decrease by 1 for next move if needed
135 stepper.run(); // Start moving the stepper
136 delay(5);
137 }
138
139 initial_homing = 1;
140
141 while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
142 stepper.moveTo(initial_homing);
143 stepper.run();
144 initial_homing++;
145 delay(5);
146 }
147 // Zero AccelStepper
148 stepper.setCurrentPosition(steps[0]);
149
150 digitalWrite(home_led, HIGH); //Turn on the LED
151 targetTrack = 0;
152 enteredTrack = 0;
153 sCurrentPosition = sTargetTrack; // Change to string for display
154 sStepCount = String(stepper.currentPosition());
155 sEnteredTrack = "";
156 drawnokiascreen1(); // Update display
157
158 digitalWrite(sleep_pin, HIGH);
159
160 // Set operational speeds and microsteps
161 setMicrosteps(8); // Set 1/8 steps
162 stepper.setMaxSpeed(100.0); // Set Max Speed of Stepper (Faster for regular movements)
163 stepper.setAcceleration(25.0); // Set Acceleration of Stepper
164
165 }
166
167 //====================================================
168
169 void loop() {
170 long newStepCount;
171 static long lastStepCount = 0;
172 static boolean once = false;
173 static bool estop = false;
174 // The above only get executed once however many times the loop runs
175
176 if (checkKB() == '#') {
177 digitalWrite(StepperEnable, enable);
178 startTT();
179 once = true; // Update the screen only once at end of movement
180 estop = false; // Reset estop flag
181 }
182 if (stepper.distanceToGo() != 0) { // The motor still needs to run
183 stepper.run(); // Not at exit yet
184 newStepCount = stepper.currentPosition();
185 if (newStepCount!=lastStepCount){ // Only print if it's changed
186 lastStepCount = newStepCount;
187 if (newStepCount % 48 == 0){ // Only every 48 steps, more often interferes with operation
188 sStepCount = String(newStepCount);
189 lastStepCount = newStepCount;
190 drawnokiascreen1(); // Update display
191 }
192 }
193 // Check for emergency stop pressed
194 if ( !digitalRead(EmergStop) && !estop ) {
195
196 // Now tell software to stop motor, but only once so set estop flag
197 stepper.stop(); // Tell software to stop motor
198 estop = true;
199 digitalWrite(EmergStop_led, HIGH); // Turn on emergency stop LED
200 }
201 }
202 if (stepper.distanceToGo() == 0) { // The motor is stopped but has it just stopped?
203 if (once) { // Just stopped so update the display and reset reversed once and estop
204 sCurrentPosition = sTargetTrack; // Change to string for display
205 sStepCount = String(stepper.currentPosition()); // Adds steps to display at end of move
206 sEnteredTrack = "";
207 drawnokiascreen1(); // Update display
208 reversed = false; // Reset reversed etc
209 once = false;
210 estop = false;
211 }
212 }
213
214 }
215
216 //====================================================
217
218 char checkKB() {
219 char keypressed;
220 keypressed = keypad.getKey();
221 switch (keypressed) {
222 case NO_KEY :
223 break; // Nothing to do
224 case '#': // Start TT moving
225 return keypressed;
226 break;
227 case 'A' :
228 reversed = !reversed;
229 sTargetTrack = String(enteredTrack); // Change to string for display
230 if ( reversed ) {
231 sTargetTrack = String(-enteredTrack); // Indicate reversed for display
232 }
233 sEnteredTrack = sTargetTrack;
234 drawnokiascreen1(); // Update display
235 break;
236 case '*' :
237 enteredTrack = 0;
238 sEnteredTrack = "";
239 drawnokiascreen1(); // Update display
240 break;
241 case '0' ... '9' :
242 enteredTrack = (enteredTrack * 10) + (keypressed - '0');
243 // Converts keypressed to integer and builds multidigit number
244 if (enteredTrack > NUMTRACKS) {
245 enteredTrack = NUMTRACKS; // Not past the last track
246 }
247 sTargetTrack = String(enteredTrack);
248 if ( reversed )
249 sTargetTrack = String(-targetTrack); // Indicate reversed
250 sEnteredTrack = sTargetTrack;
251 drawnokiascreen1(); // Update display
252 break;
253 case 'B':
254 // Do code here but better to return 'B';
255 // And call a function or call the function here
256 break;
257 case 'C':
258 JoyStick(1);
259 break;
260 case 'D':
261 //
262 break;
263
264 } // End of switch
265 return ' ';
266 }
267
268 //====================================================
269
270 void startTT() {
271
272 stepper.moveTo(calcSteps(enteredTrack, basicStepsPerRev , microStepsPerFullStep, reversed));
273 // Go to new position
274
275 sCurrentPosition = String("mvng"); // Indicate a move is in progress
276
277 targetTrack = enteredTrack; // Remember targetTrack
278 sTargetTrack = String(targetTrack); // Change to string for display
279 if ( reversed ) {
280 sTargetTrack = String(-targetTrack); // Indicate reversed for display
281 }
282 enteredTrack = 0; // Prepare for next track input
283 sStepCount = String(stepper.currentPosition());
284 sEnteredTrack = sTargetTrack;
285 drawnokiascreen1(); // Update display
286 }
287
288
289 //====================================================
290
291 void setMicrosteps(int stepsPer) {
292 /*
293 Configure MS1 & 2 of easydriver and also set
294 value of microStepsPerFullStep to the corresponding value
295 and update Accelstepper current position in terms of
296 new step setting.
297 When reducing number of micro steps rounding errors can
298 cause step alignment errors.
299 If decreasing microsteps check if
300 stepper.currentPosition() MOD current microsteps is zero
301 If not move the stepper in steps until it is
302 */
303 switch (stepsPer) {
304 case 1 :
305 digitalWrite(MS1, 0); // (1) Full Step
306 digitalWrite(MS2, 0);
307 break;
308 case 2:
309 digitalWrite(MS1, 1); // (2) Half Step
310 digitalWrite(MS2, 0);
311 break;
312 case 4 :
313 digitalWrite(MS1, 0); // (4) Quarter Step
314 digitalWrite(MS2, 1);
315 break;
316 case 8:
317 digitalWrite(MS1, 1); // (8) Eighth Step
318 digitalWrite(MS2, 1);
319 break;
320 default: // Default is 8 microsteps
321 digitalWrite(MS1, 1);
322 digitalWrite(MS2, 1);
323 stepsPer = 8;
324 }
325 if (stepsPer == microStepsPerFullStep) {
326 microStepsPerFullStep = stepsPer;
327 return;
328 } // Handles initial setup the very first time called
329
330 // Check for non MOD = 0 current position
331 int oddsteps = stepper.currentPosition() % microStepsPerFullStep;
332 if ((stepsPer < microStepsPerFullStep) && (oddsteps != 0)) {
333 // Need to move until oddsteps is zero
334 stepper.move(microStepsPerFullStep - oddsteps); // Relative move
335 stepper.runToPosition(); // Does the move
336 }
337 // Now adjust for new step setting
338 long currentSteps = stepper.currentPosition(); // Read current position
339 currentSteps = currentSteps * stepsPer; // Multiply by new setting
340 currentSteps = (currentSteps / microStepsPerFullStep); // And divide by the old
341 stepper.setCurrentPosition(currentSteps); // And write it back
342 microStepsPerFullStep = stepsPer; // Save new setting
343 }
344
345
346 //===================================================
347
348 void drawnokiascreen1() { // Screen display #1
349 u8g.firstPage();
350 do {
351 u8g.drawHLine(0, 15, 84); // Draw top horizontal line
352 u8g.drawVLine(50, 0, 47); // Draw vertical line
353 u8g.drawHLine(0, 35, 84); // Draw bottom horizontal line
354 u8g.setFont(u8g_font_profont11); // Set font
355 u8g.drawStr(4, 10, "cur-pos");
356 u8g.setPrintPos(57, 14);
357 u8g.print(sCurrentPosition); // Display current position
358 u8g.drawStr(4, 29, "step #");
359 u8g.setPrintPos(57, 29);
360 u8g.print(sStepCount); // Display current step count of stepper
361 u8g.drawStr(4, 46, "new-pos");
362 u8g.setPrintPos(57, 47);
363 u8g.print(sEnteredTrack); // Display new track #
364 }
365 while ( u8g.nextPage() );
366 }
367
368 //====================================================
369
370 void drawnokiascreen2() { // Screen display #2
371 u8g.firstPage();
372 do {
373 u8g.drawHLine(0, 15, 84);
374 u8g.drawVLine(50, 15, 47);
375 u8g.drawHLine(0, 35, 84);
376 u8g.setFont(u8g_font_profont11);
377 u8g.drawStr(4, 10, "joystick mode"); // Display "Joystick Mode"
378 u8g.setPrintPos(57, 14);
379 u8g.print(sCurrentPosition); // No display here in Joystick mode
380 u8g.drawStr(4, 29, "step #");
381 u8g.setPrintPos(57, 29);
382 u8g.print(sStepCount); // Display step count of stepper
383 u8g.drawStr(4, 46, "stp-spd");
384 u8g.setPrintPos(57, 47);
385 u8g.print(sEnteredTrack); // Display step speed of stepper
386 }
387 while ( u8g.nextPage() );
388 }
389
390 //====================================================
391
392 // Shortest path to new track
393
394 long calcSteps(int destination, long FullstepsPerRev, long microSteps, boolean alignReversedEnd) {
395 long microStepsPerRev = FullstepsPerRev * microSteps;
396 long stepsFor180 = microStepsPerRev / 2;
397
398 // Read current position and transfor into the range 0 to microStepsPerRev
399 long currentSteps = stepper.currentPosition();
400
401 currentSteps = currentSteps % microStepsPerRev; // Reduce below steps /rev
402 if (currentSteps < 0) currentSteps = currentSteps + microStepsPerRev; // Make -ve's +ve
403
404 // Update AccelStepper with the 0 to microStepsPerRev range position
405 stepper.setCurrentPosition(currentSteps);
406
407 // Now get the steps for the new destination and add 1/2 rev if reversed
408 long newSteps = steps[destination]* microSteps;
409 if (alignReversedEnd) {
410 newSteps += stepsFor180;
411 newSteps = newSteps % microStepsPerRev; // No point in doing more than 1 rev!!
412 }
413 // If less than or equal to a half rev we are done
414 if (abs(newSteps - currentSteps) <= stepsFor180) return newSteps; // EXIT all done
415
416 // If we are here the number of steps is more than stepsFor180 so we need to reverse
417 //direction from the 'norm'
418 if (newSteps < currentSteps) {
419 // Convert CCW to CW
420 return newSteps += microStepsPerRev; //EXIT
421 } else {
422 // Convert CW to CCW
423 return newSteps -= microStepsPerRev; //EXIT
424 }
425 }
426 //====================================================
427
428 void JoyStick(int Microsteps) {
Summary:
Note: The full version of this sketch can be downloaded through the MRH-rrworks-collab.io website and requires membership which is not complicated. Follow this link (click here). Please note that this sketch is copyrighted and not intended for sale or distribution. Intended only for individual use.
The turntable can be the center of attention and operation for your engine facility. Manually controlling the bridge with a hand-wheel and gear connection is a quick and easy way to get things in operation but there's a better way and it doesn't cost an arm and a leg. In fact, the cost is comparable to setting up a hand crank with gear reduction and u-joints. Maybe the only real disadvantage to manual control is that you have to be able to clearly see the bridge location to get the tracks lined up. This sketch and associated parts were developed because the turntable is located over 2' from where the operator stands and his vision isn't what it used to be. This is the perfect application for a stepper motor. It's accurate and stops are repeatable. Motion can be programmed to suit your eye. The motion is really the star here because it's realistically smooth and slow and that ramp-up and ramp-down of speed is the cat's meow. Another advantage to remote Arduino operation is that you can quickly punch in your command and then just observe as the turntable goes through it's operation just like there were two 1.5" tall guys in dirty blue overalls leaning into those push-bars.
This sketch was designed for easy operation. Most of it is intuitive and the explanation of code throughout makes for easy-to-understand commands. It doesn't take long before you're going through the sketch and modifying things for your own application. And then once you have all of your track locations added in it's just a matter of deciding where you want to go, entering a number and enjoying the show.
Subscribe to:
Posts (Atom)
Painting Plaster Castings
Today I painted the remaining walls of the roundhouse and thought I'd add a blurb here to share my technique for painting plaster stone...
-
This is an article I wrote for a book, "Arduino Intermediate Model Railroad Projects" by Paul and David Bradt. The book is availa...
-
In Pt 1 I said something about looking for an HO Bachmann Shay on eBay. I did look but in the end decided on an On30 Bachmann Shay. The...
-
Two years ago, April 2018, I started to build a diesel Shay based on several photos of the prototype built by Canadian Forest Products...