Jump to content
 

Deev

Members
  • Posts

    199
  • Joined

  • Last visited

Everything posted by Deev

  1. Yes, I've seen that. Everything about that layout is something else. Simply a masterpiece. Regarding the costs, hard to give a definitive figure, but here are my guesses: 1 x Controller (Einsy Rambo) = £70 1 x Optocoupler board = £5 4 x NEMA 17 stepper motors - 4 x £15 = £60 4 x 8mm leadscrews with POM nuts = 4 x £15 = £60 2 x pairs 600mm drawer runners - 2 x £10 = £20 Aluminium section = £30 Sheet of 15mm Plywood = £100 Cable chain = £10 200w Power supply = £20 Screws, glue, microswitches, bolts = £20 TOTAL = £395 Add to this the track and copper-clad. I may point out that you could buy a lot of points and motors for £400.
  2. Hi Hector, Well, I like your plans - I'm always a massive fan of complex multi-level layouts. What I will say is that the traverser looks quite short. I don't know what length trains you'll be running, but I reckoned on a traverser about 2500mm long to allow a full length HST set to be moved. If you're running shorter rakes, then this won't be an issue. This said, your layout might look better served using more traditional points and servo motors to avoid the obvious complexity, not to mention the cost, of scratch-building a traverser. If you are after the technical challenge of it, then I commend you. Other considerations are the amount of space in front of and behind the traverser you'd need to allow it to traverse. Also, have you considered building a helix so that you have the possibility of a second traverser? How are you going to run cabling to the traverser? Are you going to fit sensors on it to automatically stop trains? A cable chain might be a worthwhile investment here. My final thoughts are with a traverser, to buy the most expensive and powerful mechanism you can. Depending on the length of the traverser, and the amount of stock on it, you're liable to have a lot of weight to shift, so you'll probably need multiple NEMA17s, say four at least by my reckoning. If I were building one, I'd use the best mechanisms I could find (8mm diameter, 8mm pitch, 4 threaded leadscrews with POM (not brass) nuts and use an Einsy Rambo control board, purely because all the hard work is done for you and it can run 4 steppers silently. Having a noisy stepper driver would drive you insane after a while. It would be annoying to build a traverser cheaply and then curse every time it jammed or stopped working.
  3. I managed to get one of these working, but it wasn't easy and I moved house before I could take acceptable photos of it. My experience is that you need provide much more power than you think you'll need, but drawer runners are the things to use as they are fiendishly accurate. I'd look at a 3d-printer driver board and NEMA17 motors. The world of 3d printers has exploded over the last 10 years and you can buy a fully-populated motherboard that includes the Arduino, silent motor drivers (eg. TMC2208) as well as all the connectors for things like limit switches for less than £60.. Search for Einsy RAMBO. Obviously you'll need to write your own code for it (and before you ask, I've lost the code that I wrote) but it isn't actually that difficult. You'll also need to work out a way of calibrating it, either through limit switches or through stall-monitoring through back-EMF.
  4. Hi Adam, I can't remember exactly how I did it, probably set a 'float' with the number of the road in it. I lost my code, so will have to start again on it. Dave
  5. Interesting. I'd looked at the NEMA23 and was surprised how high the current draw on them was, which is something I was hoping to avoid. Instead I was planning on using 8 x NEMA17 motors directly mounted to 8mm 4-lead leadscrews with a balancing gas strut to help the lift.
  6. I recently travelled from London Heathrow to Filton Abbeywood and noticed this whilst waiting for a security check to take place on the platform at T5. Looks like the doors of the Heathrow Express run on what are basically drawer runners, making me think that they'll be more than adequate for my vertical storage yard.
  7. Wow, that's fantastic. Would love to see it in action, can you upload to YouTube then post the link?
  8. This is a note to self post rather than noting any progress. Height of stock + track = 55mm. 65mm would give ample clearance, so 70mm between top of bed and bottom of mechanism.
  9. Hi JD, I'm curious as to why you're using a photo interruptor? Can you explain? Anyway, if you take a look at the link to my Filton Abbeywood thread (link on my signature) you'll find the code and some experimentation with the HES. Note: the code is for RS485 and JMRI. Let me know if it works.
  10. Hi JB, It'd be a useful skill - ou can tailor your own code that way, and use the Arduino to do pretty much whatever you want. I've managed to get mine to work as a position feedback sensor! Dave
  11. Solved it! The problem lay with the Arduino code. I reprogrammed it to call an interrupt when the Hall Effect Sensor went high, and hey presto, it worked!
  12. No problem, I don;t know that it'll actually work as I've not been able to test it!
  13. 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; } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. 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
  15. Indeed, I can't work it out. It seems that the sensor signal needs to be high for over 1500ms for anything to be registered. You can see on this video that JMRI receives the command when the LED is illuminated, but it takes a while to send a command to stop the loco. https://www.youtube.com/watch?v=25814O0xUBE Somethings not right so I'll check the JMRI user group - thanks for the tip. Dave
  16. 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.
  17. I'm impressed by RocRail as well, I'm persevering with JMRI as it allows me to interface directly to devices via a RS485 us, which isn't something I've found that RocRail can do. Dave
  18. Interesting - what DCC hardware do you use? I use a Lenz Set 100 with LI-USB.
  19. I've been doing some notice JMRI position detection and have written a simple script. There seems to be a significant delay (3000ms+) between the input coming from the Arduino to the loco responding (via XpressNet. Does anyone experience the same issue and is there any way of fixing it?
  20. 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
  21. 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.
  22. 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.
  23. 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.
×
×
  • Create New...