tender Posted October 29, 2013 Share Posted October 29, 2013 Hi Dave, hope your still watching this thread and things are still progressing with your project. After a 10 month lapse, I've finally got around to connecting up the Arduino board to the stepper motor. I had originally thought of doing a traverser but my attention now is for a turntable. I've been playing around with a PECO turntable with the stepper motor directly connected to the bridge shaft and I find I can control the motor very well without hardly any jitter and get precise alignment. Next step is to get the DCC part working hence my 'bump' on here. I remembered you had a number of zip files for the DCC side of the Arduino code but none of the links seem to be working. Are these still available. Best regards Ray. Link to post Share on other sites More sharing options...
Deev Posted October 29, 2013 Author Share Posted October 29, 2013 (edited) Hi Ray, My plans for the 'Ultimate' traverser have stopped as I'll be moving house next year to a place with a dedicated 6x2.5m railway room. As such, I won't need one as I'll have space to use points! However, I do still have the code, see below. Let me know if you need help and I'll see what I can do. https://skydrive.live.com/embed?cid=C6CFE21E43493368&resid=C6CFE21E43493368%21159&authkey=ANFaOxzOQgfUx0I https://skydrive.live.com/embed?cid=C6CFE21E43493368&resid=C6CFE21E43493368%21160&authkey=ANB2K9orPIVwORc https://skydrive.live.com/embed?cid=C6CFE21E43493368&resid=C6CFE21E43493368%21156&authkey=AGrKuRh4uU7kjO8 Dave Edited October 29, 2013 by Deev Link to post Share on other sites More sharing options...
MattWallace Posted October 30, 2013 Share Posted October 30, 2013 Hi Dave, Are you happy for me to take that code and publish it on Github (or could you publish it yourself?)? I'm starting to add various train-related "stuffs" to my github account to share and have people improve (JMR-Pi is just the start of it!). I'd hate to see you move away from skydrive and have to repeat the "please can we have the code? yes, it's now on google drive" all over again! Cheers, Matt Link to post Share on other sites More sharing options...
Deev Posted October 30, 2013 Author Share Posted October 30, 2013 Yes, publish it wherever you like. Link to post Share on other sites More sharing options...
gadge1971 Posted February 13, 2014 Share Posted February 13, 2014 Hi Dave, I've just come across this thread and its exactly what I was looking for. I'm planning to build two traversers for a large loft layout. I've been pondering how to control stepper motors without huge expense and you seem to have managed it. I will read through the whole thread Cheers Dave Link to post Share on other sites More sharing options...
tender Posted February 13, 2014 Share Posted February 13, 2014 Hi Dave. You might want to have a look at this thread as well. Its for a DCC controlled turntable but uses the same Arduino, Stepper system and the code would work just as well for a traverser. Just the mechanics that are different. Ray. Link to post Share on other sites More sharing options...
Deev Posted February 13, 2014 Author Share Posted February 13, 2014 Hi Dave, Good to see that this thread isn't dead! As mentioned, I'm not proceeding any further with this traverser as I'll be moving house soon. I did, however, do a lot of work on the design which I'm happy to share. For a decent size traverser, and by that I mean, 3000mm+, I think that 2 x steppers would be best. This gives double the power as well as solving the parallax problem of one motor drive. It's also cheaper than employing a drive system. The Arduino and Motor shield can easily handle 2 steppers and they can be programmed to work in unison. As the motor shield has the capability to drive 2 x servos as well as the steppers, these could be used for aligning the track. This would lock the traverser in place so that when the power is off it won't move. Something like a bathroom lock could be employed for this. When you've got a decent starting point, the steppers just won't go out of position, even after hours of operation. As for the drive, I reckon that a tensioned belt is not only the cheapest but also the best solution. There are details how to tension it in this thread elsewhere. It would be interesting to see how you get on with this, please post photos! Dave Link to post Share on other sites More sharing options...
gadge1971 Posted February 13, 2014 Share Posted February 13, 2014 Hello Gents, Thanks for the info as I was going mad trying to work out how I was going to even start on this project. Dave, I have seen some linear solenoids that are 12-24v and have a linear displacement of about 15-20mm. I planned to use these as locking bolts at either end. Length wise they will both be 2800-3000mm long each having about 6 lanes with standing spacing. I'm using a Lenz DCC system and I will need occupancy detection as both tables will be underneath the main scenic boards. Ray I will take a look at the turntable thread as I am planning on two turntables at the ends of the tables as the layout is designed as end to end. I would upload my plans for you both to scrutinise but I'm not sure how to add attachments on here. Link to post Share on other sites More sharing options...
Simond Posted February 14, 2014 Share Posted February 14, 2014 "More reply options" & "choose file" Bon chance! SD Link to post Share on other sites More sharing options...
gadge1971 Posted February 14, 2014 Share Posted February 14, 2014 Thanks! I was trying to reply on my iPad which sometimes omits certain parts of the website. Dave Link to post Share on other sites More sharing options...
jbsorocaba Posted April 17, 2014 Share Posted April 17, 2014 Hello Gents, Thanks for the info as I was going mad trying to work out how I was going to even start on this project. Dave, I have seen some linear solenoids that are 12-24v and have a linear displacement of about 15-20mm. I planned to use these as locking bolts at either end. Length wise they will both be 2800-3000mm long each having about 6 lanes with standing spacing. I'm using a Lenz DCC system and I will need occupancy detection as both tables will be underneath the main scenic boards. Ray I will take a look at the turntable thread as I am planning on two turntables at the ends of the tables as the layout is designed as end to end. I would upload my plans for you both to scrutinise but I'm not sure how to add attachments on here. Hi gadget1971 I am waiting since february for your post with plans, I am very insteristing in this threads, and my traverse is in standby waiting a solucion to work. Have you finish yours. Tks Link to post Share on other sites More sharing options...
Deev Posted September 12, 2014 Author Share Posted September 12, 2014 (edited) I've not given up on the traverser but have had a few other things going on to occupy my time lately. I notice that 'The Germans' have redesigned their traverser for undisclosed reasons: Looks like an almighty amount of electronics compared to what I was planning. Edited September 12, 2014 by Deev 1 Link to post Share on other sites More sharing options...
Simond Posted September 12, 2014 Share Posted September 12, 2014 'tis ferocious in the sheer quantity of electrickery. it appears to include train control as well as control of the traversers themselves, and there appears to be logic in that it finds, and checks, that the road is clear before sending a train in / out and screens for the despatchers, and, and... there must be more than a few lines of code in there too. very clever! music would drive you up the wall tho'! Simon Link to post Share on other sites More sharing options...
Deev Posted September 12, 2014 Author Share Posted September 12, 2014 Yes I agree it's clever but isn't all that the job of a PC? I can't work out why they've done it with discrete components. Link to post Share on other sites More sharing options...
RMweb Gold Trevellan Posted September 12, 2014 RMweb Gold Share Posted September 12, 2014 Whatever the questions over the spec, it's an impressive piece of work and a good use of the space available over a conventional ladder yard with turnouts. Link to post Share on other sites More sharing options...
Deev Posted September 12, 2014 Author Share Posted September 12, 2014 Too true! Can't argue with that. Link to post Share on other sites More sharing options...
Deev Posted September 18, 2014 Author Share Posted September 18, 2014 After a bit of research, I arrived at the fact that JMRI is probably the best way of controlling a traverser. Helpful that it would be to be able to use a handset, it's not very intuitive. In theory , utilising JMRI means that the USB of the PC can be used to control the layout, instead of burdening the DCC signal with more signals. Simple enough, but the next challenge is to find a way of connecting an Arduino to the USB. Helpfully, it looks like the hard bit has already been done here: http://www.utrainia.com/65-arduinocmri-and-rs485 In short, using an RS485 bus allows multiple Arduinos to communicate with the PC and therefore JMRI via USB. As inputs / outputs are cheap and plentiful on the Arduino (the Mega has 54 digital I/O ports, plus another 16 analogue I/O ports!) it got me wondering whether to use the RS485-connected Arduino(s) to control the point motors (and allow feedback) as well as to play sounds (I want proper realistic station announcements on my stalled FAW project) and provide train position detection. I'm working on a smaller traverser now to test the concept and hope to facilitate train location to accurately stop the trains in the right place. Link to post Share on other sites More sharing options...
jbsorocaba Posted October 18, 2014 Share Posted October 18, 2014 After a bit of research, I arrived at the fact that JMRI is probably the best way of controlling a traverser. Helpful that it would be to be able to use a handset, it's not very intuitive. In theory , utilising JMRI means that the USB of the PC can be used to control the layout, instead of burdening the DCC signal with more signals. Simple enough, but the next challenge is to find a way of connecting an Arduino to the USB. Helpfully, it looks like the hard bit has already been done here: http://www.utrainia.com/65-arduinocmri-and-rs485 In short, using an RS485 bus allows multiple Arduinos to communicate with the PC and therefore JMRI via USB. As inputs / outputs are cheap and plentiful on the Arduino (the Mega has 54 digital I/O ports, plus another 16 analogue I/O ports!) it got me wondering whether to use the RS485-connected Arduino(s) to control the point motors (and allow feedback) as well as to play sounds (I want proper realistic station announcements on my stalled FAW project) and provide train position detection. I'm working on a smaller traverser now to test the concept and hope to facilitate train location to accurately stop the trains in the right place. Hi Deev Any news about the new traverser;;? Cheers Link to post Share on other sites More sharing options...
Deev Posted October 19, 2014 Author Share Posted October 19, 2014 Hi JB, No, not really, my new railway room construction project is taking rather a lot of my time. However, I have been doing a bit of playing with the 485 bus and the Arduino. I ordered a couple of Arduino Nanos and their corresponding screw connector boards to allow me to fit them to the layout, which after a 4 week lead time have arrived. Also arrived, are a huge number of MAX485 chips to allow me to connect them all together. I've managed to get the Arduino to act as a JMRI sensor / switch so the next step is to see if I can get several of them to work together. Also, I've bought a few Hall Effect Sensors to see if the Arduino can do position sensing as well, I just need a few evenings to play now! D 2 Link to post Share on other sites More sharing options...
jbsorocaba Posted November 16, 2014 Share Posted November 16, 2014 Hi guys Any news of this interesting project..? JB Link to post Share on other sites More sharing options...
Deev Posted November 16, 2014 Author Share Posted November 16, 2014 (edited) Not yet, I've been somewhat distracted by the prospect of interfacing the Arduino directly to JMRI via RS485 rather than via DCC. More details on my Filton Abbeywood thread. Edited November 16, 2014 by Deev Link to post Share on other sites More sharing options...
jbsorocaba Posted November 22, 2014 Share Posted November 22, 2014 Hi Deev I am working in a traverser just like your, but I dont want to complicate the things. My intention is to stop in position of post #57, using the arduino just like an accessory decoder, "calling " the tracks through the command. But I am in bad situation, because the final code ( post# 57 ) is no more there. Could you please send me the code just like you made on the post # 57 Tks Link to post Share on other sites More sharing options...
Deev Posted November 23, 2014 Author Share Posted November 23, 2014 Hi JB, Sorry, I can't because I don't have it any more. Have a look at post #80 as there are links to some code there. You'll probably have to do some rewriting of the code as it is very unlikely that it'll do exactly what you want. Always good to practice some Arduino code writing though! DAve Link to post Share on other sites More sharing options...
jbsorocaba Posted November 23, 2014 Share Posted November 23, 2014 Hi JB, Sorry, I can't because I don't have it any more. Have a look at post #80 as there are links to some code there. You'll probably have to do some rewriting of the code as it is very unlikely that it'll do exactly what you want. Always good to practice some Arduino code writing though! DAve Hi Deev Thank you for your prompt response. The codes at post #80 are about accessory decoder and stepper 6 ( the first one that you post here ) The challenge is to put all together ( if this procedure is correct ) to have a code just like in your post # 57 because I dont know nothing about Arduino language ( I only know to make connections ) lol.... Link to post Share on other sites More sharing options...
Deev Posted November 24, 2014 Author Share Posted November 24, 2014 Try the code below. It might work. Use accessory decoder addresses 711 to 717. Dave #include <DCC_Decoder.h> #include <AFMotor.h> AF_Stepper motor(200, 1); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Defines and structures // #define kDCC_INTERRUPT 0 typedef struct { int address; // Address to respond to byte output; // State of output 1=on, 0=off int road; // Position of road on the traverser boolean isDigital; // true=digital, false=analog. If analog must also set analogValue field boolean isFlasher; // true=flash output, false=no time, no flash. byte analogValue; // Value to use with analog type. int durationMilli; // Milliseconds to leave output on for. 0 means don't auto off unsigned long onMilli; // Used internally for timing unsigned long offMilli; // } DCCAccessoryAddress; DCCAccessoryAddress gAddresses[8]; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Decoder Init // void ConfigureDecoder() { gAddresses[0].address = 711; gAddresses[0].output = 1; gAddresses[0].road = 0; gAddresses[0].isDigital = true; gAddresses[0].isFlasher = false; gAddresses[0].analogValue = 250; gAddresses[0].durationMilli = 0; gAddresses[1].address = 712; gAddresses[1].output = 1; gAddresses[1].road = 1; gAddresses[1].isDigital = true; gAddresses[1].isFlasher = false; gAddresses[1].analogValue = 0; gAddresses[1].durationMilli = 0; gAddresses[2].address = 713; gAddresses[2].output = 0; gAddresses[2].road = 2; gAddresses[2].isDigital = true; gAddresses[2].isFlasher = true; gAddresses[2].analogValue = 250; gAddresses[2].durationMilli = 500; gAddresses[3].address = 714; gAddresses[3].output = 0; gAddresses[3].road = 3; gAddresses[3].isDigital = true; gAddresses[3].isFlasher = true; gAddresses[3].analogValue = 0; gAddresses[3].durationMilli = 500; gAddresses[4].address = 715; gAddresses[4].output = 0; gAddresses[4].road = 4; gAddresses[4].isDigital = true; gAddresses[4].isFlasher = false; gAddresses[4].analogValue = 250; gAddresses[4].durationMilli = 0; gAddresses[5].address = 716; gAddresses[5].output = 0; gAddresses[5].road = 5; gAddresses[5].isDigital = true; gAddresses[5].isFlasher = false; gAddresses[5].analogValue = 0; gAddresses[5].durationMilli = 0; gAddresses[6].address = 717; gAddresses[6].output = 0; gAddresses[6].road = 6; gAddresses[6].isDigital = true; gAddresses[6].isFlasher = false; gAddresses[6].analogValue = 0; gAddresses[6].durationMilli = 0; gAddresses[7].address = 718; gAddresses[7].output = 0; gAddresses[7].road = 7; gAddresses[7].isDigital = true; gAddresses[7].isFlasher = false; gAddresses[7].analogValue = 0; gAddresses[7].durationMilli = 0; // // Setup output pins // for(int i=0; i<(int)(sizeof(gAddresses)/sizeof(gAddresses[0])); i++) // { // if( gAddresses.outputPin ) // { // pinMode( gAddresses.outputPin, OUTPUT ); // } // gAddresses.onMilli = 0; // gAddresses.offMilli = 0; // } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Basic accessory packet handler // void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data) { // Convert NMRA packet address format to human address address -= 1; address *= 4; address += 1; address += (data & 0x06) >> 1; boolean enable = (data & 0x01) ? 1 : 0; for(int i=0; i<(int)(sizeof(gAddresses)/sizeof(gAddresses[0])); i++) { if( address == gAddresses.address ) { // Serial.print("Basic addr: "); // Serial.print(address,DEC); // Serial.print(" activate: "); // Serial.println(enable,DEC); if( enable ) { gAddresses.output = 1; gAddresses.onMilli = millis(); gAddresses.offMilli = 0; }else{ gAddresses.output = 0; gAddresses.onMilli = 0; gAddresses.offMilli = millis(); } } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Setup // int posn = 0; void setup() { // DCC setup Serial.begin(9600); // set up Serial library at 9600 bps DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true); ConfigureDecoder(); DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT ); // Stepper setup motor.setSpeed(90); // 90 rpm } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Main loop // void loop() { static int addr = 0; //////////////////////////////////////////////////////////////// // Loop DCC library DCC.loop(); //////////////////////////////////////////////////////////////// // Bump to next address to test if( ++addr >= (int)(sizeof(gAddresses)/sizeof(gAddresses[0])) ) { addr = 0; } //////////////////////////////////////////////////////////////// // Turn off output? // if( gAddresses[addr].offMilli && gAddresses[addr].offMilli<millis() ) // { // // Clear off time // gAddresses[addr].offMilli = 0; // // // Disable output // if( gAddresses[addr].isDigital ) // { // digitalWrite( gAddresses[addr].outputPin, LOW); // }else{ // analogWrite( gAddresses[addr].outputPin, 0); // } // // // If still enabled and a flash type, set on time // if( gAddresses[addr].output && gAddresses[addr].isFlasher) // { // gAddresses[addr].onMilli = millis() + gAddresses[addr].durationMilli; // }else{ // gAddresses[addr].output = 0; // } // // return; // } //////////////////////////////////////////////////////////////// // Turn on output? if( gAddresses[addr].onMilli && gAddresses[addr].onMilli<=millis() ) { // Clear off time gAddresses[addr].onMilli = 0; // Enable output if(gAddresses[addr].road-posn == 0) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: 0"); posn = gAddresses[addr].road; Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -1) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -1"); posn = gAddresses[addr].road; motor.step(250, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -2) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -2"); posn = gAddresses[addr].road; motor.step(500, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -3) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -3"); posn = gAddresses[addr].road; motor.step(750, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -4) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -4"); posn = gAddresses[addr].road; motor.step(1000, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -5) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -5"); posn = gAddresses[addr].road; motor.step(1250, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -6) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -6"); posn = gAddresses[addr].road; motor.step(1500, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == -7) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: -7"); posn = gAddresses[addr].road; motor.step(1750, BACKWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 1) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +1"); posn = gAddresses[addr].road; motor.step(250, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 2) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +2"); posn = gAddresses[addr].road; motor.step(500, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 3) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +3"); posn = gAddresses[addr].road; motor.step(750, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 4) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +4"); posn = gAddresses[addr].road; motor.step(1000, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 5) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +5"); posn = gAddresses[addr].road; motor.step(1250, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 6) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +6"); posn = gAddresses[addr].road; motor.step(1500, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else if(gAddresses[addr].road-posn == 7) { Serial.print("Position: "); Serial.println(posn, DEC); Serial.print("Moving to: "); Serial.println(gAddresses[addr].road, DEC); Serial.println("Moving: +7"); posn = gAddresses[addr].road; motor.step(1750, FORWARD, DOUBLE); Serial.print("New position: "); Serial.println(posn, DEC); Serial.println(" "); delay (200); } else { return; } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Link to post Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now