Skip to main content

Is it possible? It sure is, it just isn't very pretty yet.

For those that follow along with my posts in the LC/radio control forum you'll know this one has been coming for a while. Given that most folks here don't seem to take part in the technical discussions, however I thought it might be worthwhile to post here to get the greatest amount of feedback from others.

With LionChief/LionChief Plus, hereafter referred to as LC/LC+, there have been a number of criticisms to the system from folks of all sorts, however the biggest problem I see mentioned is the lack of compatibility with other command systems. Lionel has started to address the issue of requiring many remotes with their Universal remote, but this still does not help the folks that want to run a LC/+ engine from their Legacy or TMCC Cab remote.

I've stated many, many times that Lionel could very easily offer a device to allow control of LC/+ locomotives from the Cab1/2 remotes, but I do not believe it is in their business plan to do so. This has left the door open for folks to find a solution on their own. As it turns out, the solution is not exceptionally difficult. Thus I present the John Galt Line LC-TMCC Bridge.

Right now this is just a working prototype, and not really intended as a solution for other folks, as it requires modifying the remote to your LC locomotive. My intention is to use one of the Universal remotes in the future to make this a stan alone, plug and play, device that will not require any modifications to anything. I did spend some time on actually decoding the radio signals in use, but hit a wall after a few days and decided to take the easy way out by modifying the remote and using it's radio instead. I know this is a kludged back door way to get the job done, but it does get the job done none the less.

Here is the video demonstrating the bridge:

https://www.youtube.com/watch?v=5DhIC7HPsyU

 There are currently a few small bugs I need to work out, and some programing to be added. First, there is a bug with the 'lash-up' commands where the device has to be powered down before the engine will respond correctly to it's set starting direction. I thought I had fixed this, but when I shot the video it did not work correctly. Second, in it's current form, the device will only work on an original TMCC base, not on Legacy or the base1L. This is for two reasons. The first is solved with the addition of simple hardware to accept a true(ish) RS232 signal rather than the TTL level signal the TMCC base provides. Not difficult or expensive, but something I skipped in building the prototype here. The second problem with Legacy is that I have not programed the Bridge to respond to absolute speed steps. From mu understanding, the Legacy base sends out speed commands differently than the TMCC base, which provides a bit better control. The Bridge however is only programed to read the relitiave speed commands. I do not anticipate it being difficult to add absolute speed control, but have not done so as I do not have a Legacy base to test with. The final glitch I am aware of is that for some reason I have yet to discover the momentum moves at a slightly different speed when using the brake and boost buttons than it does when simply turning up or down the throttle knob. After spending a few hours dissecting my own code I've yet to figure out why this happens. I'm sure I'll figure it out at some point, or simply apply a kludged fix if I need to.

This is not exactly a bug, but needs to be adjusted to make the LC locomotive behave more like TMCC ones, I have to adjust the timing on the momentum setting. This is as simple as changing a variable to whatever setting I like in the program. Right now low momentum changes speeds instantly, medium at 200ms intervals, and High at 500ms intervals. I think this ended up too long compared to TMCC engines with the NW2 here “coasting” about twice as far as it should at high momentum. I may end up making this an adjustable setting so that folks can make the momentum 'coast' the engine as far, or as little, as they like.

There are also a couple of limitations to the Bridge because of the way the LC system works. First here is that there is no way for the bridge to know if the bell is ringing or turned off on the engine. Because of this pressing the '0' reset can not turn off the bell. Another limitation is that only features that the LC remote can operate can be accessed from the Bridge. Turning on and off the smoke units, or engine/chuffing sounds can not be done through the Bridge as these are controlled with physical switches on the locomotive.

The last thing of note is that while I programed the functionality into the Bridge, I don't recommend running “Lash-Ups” so far each LC+ engine I've tested moves at a bit of a different speed at each step, and this will cause them to fight each other if linked together. Train commands should work fine with two of the same model of locomotive, but will be problematic if you were to mix engine types, or mix LC and TMCC. I am unsure if I will keep 'Lash-Ups' as an option in a final version.

 

I don't expect in the current version that this is a product that could be brought to market, having to modify the remote is beyond the difficulty level most LionChief buyers would like to get involved with. Once the Universal remote is offered, or I am able to decode the digital radio data, however, I expect a bridge device that could control at least 3 different locomotives could be sold around the same price that other TMCC devices tend to be. I'll look further into marketability if it proves there is a demand for such a product. If not, I'm happy to have one for my self.

 

Thank you for your time, and I welcome your thoughts on this.

 

The John Galt Line

JGL

 

 

Last edited by JohnGaltLine
Original Post

Replies sorted oldest to newest

Hi John

     Well detailed demo. I do see a use for the blue LCD Screen at my control panel but not sure I see a use for the Cab 1, running a LionChief Plus, at this time. The blue LCD screen would be a good way to manage trains. If it could be set up to tell me what locomotive and number was on each of the 4 main lines.

     This project reminds me of my HeathKit Days.  https://www.heathkit.com/

Cheers from Train Room Gary Pan view

Attachments

Images (1)
  • Cheers from Train Room Gary Pan view

Thanks for the comment, Gary.

We could talk about the uses you have for a screen and see what is possible, and if what you want is a do-able project.  

Im my case, the screen was an afterthought.  I originally added a 7-segment display at the same time I added the run/program buttons to show which of the three possible engines was being programed.  As it turned out the mass of code in use and timing functions needed made the 7-segment LED flicker annoyingly from time to time, so I replaced it with the LCD from my parts box.  Once it was there anyway, I figured I may as well have it say everything that was going on since it took very little more programing... Honestly using an LCD with Arduino is as simple as saying :

lcd.print("some text");

JGL

Very interesting project. Looks like you have got it pretty well figured out too. I am not familiar with either the LC or TMCC stuff as I don't have any LC items and TMCC was before I got back into the hobby. It looks like you have some added features to the LC engine from what little I know abut the LC stuff. I do know that many here have complained about the LC items not being compatible with TMCC/Legacy though. There certainly could be a demand for something like this as you will probably hear when others read your post and watch your video. I think the screen for the TMCC/LC is also a great idea. That might be another project on it's own for TMCC?

I have a Legacy system, but it's a bit different. I have also dabbled with Arduino Uno's. My knowledge of them is far from good, but I do find them interesting and continue to dabble here and there. Your project is way above my level, but I will be following along. I thought your video was well done and very informative. Thanks for posting and please keep us updated.

Last edited by rtr12
Dominic Mazoch posted:

If the bridge works, the government will ban it because it works!

That is their job, isn't it?  

In seriousness, though, I can assure you it works.  As I said at the start of the thread, the method I used is not pretty, but it is effective.  

RTR12,  building a simple screen that tells you what the TMCC base is doing would not be hard at all. My program right now is displaying all of that information to the serial monitor on my computer, which was very useful as I moved through the task of programing things.  Making it display on the LCD would involve changing each line from "Serial.print(info);"  to "lcd.print(info);".  The hardest part would be figuring out how to format the information to display in 16 letters by 2 rows so I can keep using a $2 lcd screen instead of having to upgrade to one with 4 lines that costs like $5 instead.  

As for the programing of the Arduino, this project only had a couple of things that made it complex.  the Arduino has no built in timing function so you have to use a work around that is not exactly hard, but very confusing if you want it to be able to do other things while still timing something.  Honestly, though, a good percentage of the code is simple if, then statements. Ex, IF this is an engine command, and IF this command is addressed to the bridge address, and IF the command is to blow the whistle, and IF at least 405 milliseconds have pasted since the last time you pressed the whistle button, THEN blow the whistle... it adds up to a metric S-ton of code, but nothing that is really that complex.  

JGL

Boy John I'm very impressed. I hope you are going to offer this bridge soon. In any case if anyone out there ever wondered what would happen to our electronics if Lionel and MTH went away now we know that there are people like John Galt to call.

If somebody can build it somebody else can fix it, or in John's case make it better.

Terrific work John.  An excellent demonstration of what is likely down the road, either from Lionel or creative and talented individuals such as yourself.  Reminds me of the early days of TMCC 20 years ago when individuals like Mike Reagan, Bob Krivacic, Lou Niederlander, Ed Bender and others developed receivers and motor controllers for the 90 years worth of non-command locos so they could be used with TMCC.  I remember sending an MTH PS1 GG1 to Ed Bender to install his Train Brain.  Worked well. You're walking in the footsteps of giants (literally in Mike Reagan's case--he's one tall dude ).  Congratulations and thanks.

Last edited by Landsteiner

That's very cool, and it works great!

I'm curious about one comment you made about timers.  The Arduino does support timers, and I just create a basic 1ms timer interrupt and then build a count-down timer block with 1ms, 10ms, 100ms, etc. timers as needed.  Since virtually all of my realtime modules have a basic loop that just loops servicing various functions, I can set the count-down timers on the fly and simply sample them in the code.  When they reach zero, the timer interval has passed.  Adding a completion flag is a useful feature so you know that the timer interval has expired and you have yet to service the event you were timing.

GG1Man, I thank you, but when it comes to the electronics inside these newer locomotives there are quite a number of folks that know them inside and out right here on the forum.  Folks like GunRunnerJohn, GGG, and Dale Manquen come to mind, but there are many others as well.  

GRJ, I tend to avoid interrupts when at all possible, as they have a tendency to break libraries, most notably the nRF24 Lib that I expect to need with this project in the future.  That said, the timer issue was solved with what appears to be common place code to use the millis() function which reports the time since the unit was turned on.  

I wouldn't mind a look at the sort of code you are talking about, however... Maybe it is better than what I have.  Timers confused me for a little while, but I've got it down pretty well now.  I did cheat and use the delay function in a few places, but I expect to change that at some point.  

This does remind me of one other possible bug with the bridge.  It should be turned off at least once every 49 days to insure there is no glitch with an unsigned long int rolling over.  it should still work through the rollover of the clock, but I'll put the warning out there that it can not be turned on for more than 49 days at a time.  I'm not going to test this.  

JGL

Last edited by JohnGaltLine

John,

Here's one that I use in my Super-Chuffer code, it turned out I could get away with 16 bit 1ms timers, so I don't have my usual 10ms and 100ms timer blocks.  They would be updated in exactly the same way, but I'd have one timer in each lower time block that triggered the next decade of timers.  It really is pretty simple, and if you stick to only a few timers, the execution is so fast that I can't imagine it causing an issue with other processes. The last process is the actual interrupt processor, it calls the timers() function to manage my timer block.

I'd be lost without timers!

//*************************************************************
// Manage timers
//*************************************************************
//
// timers are counted down to zero and remain at zero until reset by
// the process using the timer.
//
// Note: This function is called from the timer ISR, obviously interrupts
// are disabled while this function runs for that reason.
void timers(void) {
    uint8_t i; // for loop index

    // service 1ms timers
    for (i = 0; i < TIMERS1MS; i++)
    {
        if (ms1timers[i] > 0)
          ms1timers[i]--;
    }
} // END - void timers(void)


//*************************************************************
//          INTERRUPT SERVICE ROUTINE
//*************************************************************
void interrupt isr(void)
{
    //*** Service Timer0 interrupt
    //  TMR0 overflows every 1 ms
    //  (only Timer0 interrupts are enabled)

    INTCONbits.TMR0IF = 0;          // clear interrupt flag
    TMR0 += 256-250+3;          // add value to Timer0

    // call timer routine to service all our program timers
    timers();

    // read switch state and store in local variable
    debounced_switch = CHUFF_IN;

} // END - void interrupt isr(void)

 

JohnGaltLine posted:
This does remind me of one other possible bug with the bridge.  It should be turned off at least once every 49 days to insure there is no glitch with an unsigned long int rolling over.  it should still work through the rollover of the clock, but I'll put the warning out there that it can not be turned on for more than 49 days at a time.  I'm not going to test this.  

You could always just reset yourself before the time expires.

GRJ,

What you've got is the same basic idea, but with one fault for a real time clock.  Using a for loop depends on the cpu's workload to be the same every loop of the program.  It works out fine for simple programs, and/or you input the number to count from based on the time needed. In my case I needed a timer that measured the exact same amount of time regardless of what the processor was doing in between.  With the for loop it may take 1 millisecond to do the loop when nothing else is happening, but 3ms when it needs to run several subroutines.  (times made up for the example).  What I had to do was use the Arduino's built in clock for a real time timer.  Each loop updates a variable by reading millis(), returning the exact milliseconds that the arduino has been powered up.  This value is read-only, and will loop back to 0 after reaching 4,294,967,295.  4,294,967,295 milliseconds = 4,294967 seconds = 71,582 minutes = 1,193 hours = 49.7 days.  The possibility of a glitch then occurs for a single cycle of the loop as the program subtracts the last reading in the order of 4.29billion from the rolled over clock just over 0 and returns some unknown number as a product of math with unsigned numbers.  Basically, all of the timers break at the rollover point.  To be honest it didn't seem worth fixing for an error that is unlikely to ever present, but I suppose I could add a line that says something like: IF the clock is over 4.2 billion, then pretend like you got a HALT command and don't do anything else until the clock rolls back to 0, or the device is reset.

I still can't figure out code tags on this forum...

// Timer Vars:
unsigned long currenTime = millis(); // Define primary clock var.
unsigned long timerOneStarTime = 0; /
const long timerOneInterval = 405;
byte timerOneFlag = false;
byte timerOneExpired = 1;

void timerOne() {
// currenTime = millis(); moved to main loop
if (timerOneFlag) // flag = true
{
if (currenTime - timerOneStarTime >= timerOneInterval) {
timerOneFlag = false;
timerOneExpired = 1;
}
else {
timerOneExpired = 0;
}
}
}

void timerOneStart() {
timerOneStarTime = millis();
timerOneFlag = true;
timerOneExpired = 0;
}

It is not actually very difficult, but took a while for me to figure out.  Maybe I'm just an idiot at programing... That is a legitimate possibility.  Also of note, I have a redundant variable here.  I could have just used the flag, but for some reason I decided to add another variable to be checked elsewhere in the program and used the flag only in the timer function.  If I manage to run out of memory I'll go back and change this, but right now the program takes up about half of what an UNO offers... and about 1/16th of the Mega's storage.  

JGL

 

JohnGaltLine posted:

Is it possible? It sure is....

Hi John,

     You have done a beautiful video and a remarkable project!  Lionel should hire you to do all their demonstrations and product development.

More importantly, you did what others have said was impossible.  I am sure Harold Hitchcock will be having a meeting with the guys about this tomorrow morning!  No joy at the big "L" this week!

Excellent!!!! Outstanding!!!!!!

Thanks for sharing!

Take care, Joe.

Last edited by Joe Rampolla
JohnGaltLine posted:

RTR12,  building a simple screen that tells you what the TMCC base is doing would not be hard at all. My program right now is displaying all of that information to the serial monitor on my computer, which was very useful as I moved through the task of programing things.  Making it display on the LCD would involve changing each line from "Serial.print(info);"  to "lcd.print(info);".  The hardest part would be figuring out how to format the information to display in 16 letters by 2 rows so I can keep using a $2 lcd screen instead of having to upgrade to one with 4 lines that costs like $5 instead.  

As for the programing of the Arduino, this project only had a couple of things that made it complex.  the Arduino has no built in timing function so you have to use a work around that is not exactly hard, but very confusing if you want it to be able to do other things while still timing something.  Honestly, though, a good percentage of the code is simple if, then statements. Ex, IF this is an engine command, and IF this command is addressed to the bridge address, and IF the command is to blow the whistle, and IF at least 405 milliseconds have pasted since the last time you pressed the whistle button, THEN blow the whistle... it adds up to a metric S-ton of code, but nothing that is really that complex.  

JGL

The demand is probably over as everyone moves to Legacy, but I think the display for the Cab1/1L is a neat idea all on it's own. But I have Legacy and no Cab1or Cab1L. I have both Legacy and DCS and I am not sure I would like operating a remote with no display screen like the older TMCC stuff? What you have with the LC/LC+ bridge I think will be much more popular if you decide to go further with it. I think there is a definite interest there. I imagine many would be pleased just having what you have demonstrated so far. I am not sure I recall anyone around here ever asking for a TMCC screen?

I recently got that $5 display with the 20x4 screen you mentioned. And even finally managed to get the 4 pin version (L2C, I think it was?) to work with the Arduino Uno, a pretty big feat for me (I said earlier I was a little behind).  I also ordered the serial version as a back up just in case, but haven't tried it yet since I got the other one working. Were you using the serial version, I didn't catch it in the video? If it was shown I was probably watching another part of the screen or something and missed it.

I can usually grasp the if/then stuff, but some of the other things are still a bit above me. I will be watching you and GRJ's timer discussion as I may be having a problem with that in a project I was working on. I used to program a little in MS Quick Basic and MS Basic Pro (DOS based) using a couple of add on assembler libraries for the heavy stuff, but that has been probably at least 25 years ago or so. I didn't keep up when Visual Basic came out and everything switched to Windows. The Arduino programming has some similarities, but also some differences.

John, this is the same basic technique that is used in almost all the aerospace applications I've programmed, as well as anyone else I worked with.  The key factor here is that you had to know that you could get anything you needed to get done on time.   However, I don't see where you figure that you have to get everything done in a single loop, I never even attempted to do that.  Rather, I have a simple dispatcher that is triggered off one of the timer increments that will perform specific tasks at a specified interval.  For instance, let's say I have a minimum time slice of 25 milliseconds, a typical interval for many aerospace applications.  That means I'll have an update of the most time critical elements 40 times a second.  These would typically be stuff like airspeed, vertical speed, etc.  Let's also say that I can have tasks that have to update as seldom as once a second.  I have a 25ms task dispatch clock that counts from 40 down to zero and then resets and does it all over again.  At the appropriate dispatch values, I call the proper routines to perform the necessary tasks for that time slot.  The dispatcher ends up being one giant case statement with a series of calls to the functions to be performed in that time slot, or some variation on that theme.

I have to insure that any task slot takes considerably less than the total 25 ms time slot.  The important factor here is that no combination of tasks can use more than the 25 ms time slot.  We spend quite a bit of time in the design phase to insure this doesn't happen.  The key here is the deterministic characteristic of all the tasks.  Before it ever gets out the door, we know for sure that the design goals have been met and the behavior is tested nine ways from Sunday as well.

Trust me, this works, as many of the commercial aircraft you ride on depend on the same technique for a variety of their equipment.

For most simple stuff we'll be doing in this arena, I can't see any issue in using a similar technique.  I know for sure it works in mission critical applications, so I can't believe a can't run a model train with the same logic.

Joe Rampolla posted:

 No joy at the big "L" this week!

It's fun to think this, but in all honesty, Big L could do the same thing, and much easier/more directly.  They already have the data protocol in front of them to speak directly to the LC engines without a need to 'hack' the remote.  If they want to, they can put a bridge on the market tomorrow that will offer better functionality than mine does currently.  Of course they could have also done this the day the universal remote was announced, or the day LC+ was announced, or... You get the picture.  It is my opinion that such a product with a big L on it is not in the game plan.  I tend to think they want to keep Legacy and LC/+ as separate systems where you know you are running Legacy with all the metaphorical bells and whistles when you use the Cab2, and you know you're running an entry level product when you put the LC remote in your hands.  

JGL

GRJ, it may be that you are correct.  I've always been taught to never use the speed of the processor as a clock, as it may cause problems if you try to port the code to new hardware.  As an example of this, nearly all video games written for the 8080/8086 (2MHz) PC computers became difficult when folks upgraded to the 286 or 386(>16MHz), and entirely useless on a 50MHz 486.  

With the for loop, you need to know exactly how long it takes the processor to perform all of it's functions, and that time can not change between instances of advancing the counter.  From every example and article I've been able to find on it, reading the Millis() clock is the standard practice for the Arduino for a stable timer, and the only one that is not dependent on the speed of the processor.  

I guess it doesn't matter one way or the other, as long as you know that it will take,say, exactly 25ms for the loop to count to some number.  but when the processor may take two or three times longer before advancing the counter when it gets busy, the for loop can become less accurate.  

In the applications you've mentioned, does the processor do the same thing on each and every loop, or does it sometimes do one short, simple thing, and other times do a whole bunch of operations?

Maybe I'm not understanding how this works?  As stated before, it is entirely possible I am an idiot and do not know what I'm talking about.  In the end, I don't really think it matters, or is worth anywhere near this amount of discussion as the method in place works, but it is interesting none the less.  

JGL

 

Fascinating, truly amazing keep up the good work.

 

Hm, I wonder, when I run my lionchief LC 2-4-2 it only appears to have half the speed steps of the NW2 LC+, given only the first half of the dial on ether side caused a change in speed. I wonder how that would play into keeping in pace engines with different speed step totals and ratios?

Nice work.  I think what you have done, really could be integrated for any other remote system too.  The MRC one, etc...  Build one box with those removes inside, switches to select which one, and your interface plug in.

Joe, I don't think any one or many ever said this was impossible.  Many called for it, the question always was would Lionel build it.   G

I would think the people at Lionel would be delighted that someone is sufficiently interested in their products to come up with additional toys for playing with their trains.  If commercialized, it can only increase the value of their products by increasing their versatility.  They didn't stop Mike Reagan and Bob Krivacic, or Ed Bender from coming up with reverse engineering of TMCC to make receivers available for older non-command products back in the 1990s.  I doubt they'll do anything but cheer JGL on, and congratulate themselves on the success of LionChief/LionChief +.

JohnGaltLine posted:
Joe Rampolla posted:

 No joy at the big "L" this week!

It's fun to think this, but in all honesty, Big L could do the same thing, and much easier/more directly.  They already have the data protocol in front of them to speak directly to the LC engines without a need to 'hack' the remote.  If they want to, they can put a bridge on the market tomorrow that will offer better functionality than mine does currently.  Of course they could have also done this the day the universal remote was announced, or the day LC+ was announced, or... You get the picture.  It is my opinion that such a product with a big L on it is not in the game plan.  I tend to think they want to keep Legacy and LC/+ as separate systems where you know you are running Legacy with all the metaphorical bells and whistles when you use the Cab2, and you know you're running an entry level product when you put the LC remote in your hands.  

JGL

What would really upset the big "L" (and certain forum divas) would be a Bluetooth touch screen smart phone/tablet app and device for LionChief+ locomotives.

Take care, Joe.

Last edited by Joe Rampolla

Joe, Upset the big L. Oh, Please! If the Company had any real idea of the market place and changing economics.....they would have designed a compliant system.....when designing lion chief. Even if it required some additional hardware.

We should be the ones that should be upset....I think all of us were waiting for unification of the product line. What was presented....is personally saving me lots of my income. The increase price in legacy engines....and the incompatibility of lion chief with the Companies best/most expensive remote. Sudo's to Lionel for ideas brighter then GE.

Anyway, I thank the main poster for working on a solution. A solution Lionel should have offered the day the first lion chief engine as delivered. IMHO

Last edited by shawn
JohnGaltLine posted:

GRJ, it may be that you are correct.  I've always been taught to never use the speed of the processor as a clock, as it may cause problems if you try to port the code to new hardware.  As an example of this, nearly all video games written for the 8080/8086 (2MHz) PC computers became difficult when folks upgraded to the 286 or 386(>16MHz), and entirely useless on a 50MHz 486. 

Perhaps you misunderstand what I'm talking about.  I'm not using the speed of the processor as a clock, the basic timer interrupt is a real-time value, if it's a 1ms timer, it really interrupts on a 1ms basis.  If you ported to new hardware, you would adjust whatever timer configuration you needed to insure the timer still ran at 1ms. However, also note that porting to new hardware is a pretty rare event in the aerospace world, it's a MAJOR task!  Since the hardware and software is intimately linked, they are designed and verified to work as a unit.  If you change either, there is a very extensive process you have to perform again before they are certified to be placed on an airplane.

I remember the PC game fiasco, we're taking about a totally different environment here.

The place where processor speed enters into the picture is getting all a specific time slot's tasks done in whatever fixed time you have allocated for those tasks.  When you're building something like an air data computer, the operation must be deterministic, i.e. you can't leave any doubt that it will operate the same way every time, regardless of differing data inputs.  My "perhaps unclear" description is how we normally accomplished that task.

As you say, you have it working, so this is somewhat moot.  I think your project is a great accomplishment, and I look forward to seeing your progress.

I have suggested this exact idea for a product to Lionel several times at various shows and one talk to us of the last couple of years.  The best I response I have gotten is we may look into this someday, but for now the universal remote is the direction we are going...

To me this is yet another great option to add to the Legacy family of optional products to control LC locomotives from our Legacy / TMCC system.  

I really hope that you or ERR or somebody eventually comes up with a device which you program the RF from the LC remote to a box, then you can talk the box via legacy / tmcc.  To really be feasible, it must do multiple locomotives like their universal remote.

I hope this concept evolves past the cleaver DIY phase and its a excellent POC.

Last edited by pmilazzo

GRJ,

I'm thinking the miscommunication here is just in the options open when using the Arduino IDE.  The only functions available with access to a real time clock are Delay(), which is completely useless for any complex program, and Millis() which reports the onboard clock time. I've been unable to find any other clock functions in Arduino.  Other processors do have options to use real time timers built in, and it may be that the ATmega168 does as well, but there is no way to access this from the standard programing interface.  Hence, if you want a clock that measures real time, you're stuck with the millis() read as your only option. 

Joe, 

I'm not an app developer, and have no idea even where to start to do so.  On the other hand, the actual hardware end is as simple as adding a 99cent wifi board and a level shifter/voltage divider. (The wifi board uses 3.3VDC and the Arduino I'm using uses 5VDC).  If it is a function people want, I can look into finding someone to write the app, or learn how to do it myself, and include wifi control in the bridge with minimal effort.

On the question of controlling more than one locomotive, I expect that when using a universal remote's guts, I'll be able to offer the same 3 locomotive control from one bridge...expandable to 48 LC engines for anyone that wants to buy another universal remote for every 3 engines.  In the long term, I hope to remove the need for the remotes all together, but I'm just a bit too dumb to be able to decode the radio information just now.  At some point I'll figure that out and then be able to offer a single box that can control an unlimited number of LC engines.   This, once again, is a product bigL could announce tomorrow, as they already have everything needed to release it.  

JGL

JGL,

In the Nov 2015 issue of Nuts & Volts magazine there was an article about some different ways to use timers with the Arduinos. That is if you can even read the article without subscribing? I posted a link to another N&V article for stan2004 a while back and I believe he said he could read most of it. He obtained enough info to get the meaning of the article and project anyway. He is WAY ahead of me on this stuff though, as are many others around here.

You may already know all this, but I just thought it might possibly provide some additional info? At the top of the second page, there are a couple of links to the sample code and the authors website if you are interested. If you are interested and can't read the article, I can copy it from my magazine and send it to you if you like.

John, here's a timer routine I picked up when I was doing some tinkering with the Arduino.  I used this in one that I was building a MARS light and Rule-17 lighting feature. 

I've been mostly working with the Microchip PIC lately, but timer interrupts are available for Arduino.  This is a simple timer routine, but it can be expanded to whatever you need easily.  Note they have a 10ms and 100ms timer interval as well, and they're toggling pins so you can verify operation. 

If you ported to different speed hardware, all you need is to do is change the timer reload and possibly the register mapping to adjust for the new environment.

/*
 * author: Sebastian Wallin
 * description:
 * Example on how to configure the periodical execution of a user
 * defined function (Interrupt service routine) using Timer2. This
 * example will run the function every 1ms.
 *
 * For detailed information on Timer2 configuration see chapter 17 in
 * ATMEGA328 datasheet.
 */

/* Timer2 reload value, globally available */
unsigned int tcnt2;

/* Toggle HIGH or LOW digital write */
int toggle = 0;  // 1ms timer toggle
int toggle2 = 0;  // 10ms timer toggle
int toggle3 = 0;  // 1 sec timer toggle
int timer10ms = 0;  // 10ms timer
int timer1sec = 0;  // 1 second timer

/* Setup phase: configure and enable timer2 overflow interrupt */
void setup() {
  /* Configure the test pin as output */
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);

   /* First disable the timer overflow interrupt while we're configuring */
  TIMSK2 &= ~(1<<TOIE2);

  /* Configure timer2 in normal mode (pure counting, no PWM etc.) */
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);

  /* Select clock source: internal I/O clock */
  ASSR &= ~(1<<AS2);

  /* Disable Compare Match A interrupt enable (only want overflow) */
  TIMSK2 &= ~(1<<OCIE2A);

  /* Now configure the prescaler to CPU clock divided by 128 */
  TCCR2B |= (1<<CS22)  | (1<<CS20); // Set bits
  TCCR2B &= ~(1<<CS21);             // Clear bit

  /* We need to calculate a proper value to load the timer counter.
   * The following loads the value 131 into the Timer 2 counter register
   * The math behind this is:
   * (CPU frequency) / (prescaler value) = 125000 Hz = 8us.
   * (desired period) / 8us = 125.
   * MAX(uint8) + 1 - 125 = 131;
   */
  /* Save value globally for later reload in ISR */
  tcnt2 = 131;

  /* Finally load end enable the timer */
  TCNT2 = tcnt2;
  TIMSK2 |= (1<<TOIE2);
}

/*
 * Install the Interrupt Service Routine (ISR) for Timer2 overflow.
 * This is normally done by writing the address of the ISR in the
 * interrupt vector table but conveniently done by using ISR()  */
ISR(TIMER2_OVF_vect) {
  /* Reload the timer */
  TCNT2 = tcnt2;
  timer10ms++;
  /* Write to a digital pin so that we can confirm our timer */
  digitalWrite(2, toggle == 0 ? HIGH : LOW);
  toggle = ~toggle;
  /* now service the 10ms timer */
  if (timer10ms >= 10)
  {
    timer10ms = 0;
    toggle2 = ~toggle2;
    timer1sec++;
    digitalWrite(3, toggle2 == 0 ? HIGH : LOW);
  }
  if (timer1sec >= 100)
  {
    toggle3 = ~toggle3;
    timer1sec = 0;
    digitalWrite(13, toggle3 == 0 ? HIGH : LOW);

  }
}

/* Main loop. Empty, but needed to avoid linker errors */
void loop()

{
}

 

FWIW, I haven't moved to Legacy, and unless I hit the lottery, it isn't going to happen.  I've got 3 CAB-1's and run TMCC and conventional using PM-1's and TPC's.  I would be greatly interested in an off the shelf product that would allow me to run LC/LC+ loco's using my CAB-1's instead of a bunch of individual remotes.

And, I do understand the timer stuff from experience.  Way back in the day folks used to use FOR NEXT loops in BBX to slow down screen message imaging.  Worked fine until processor speeds got REALLY FAST, then you couldn't see anything.  Started using WAIT's that were tied to the system clocks to perform the same functionality.

Fred

Add Reply

Post
×
×
×
×
Link copied to your clipboard.
×
×