element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Cool LED Display
  • Challenges & Projects
  • Project14
  • Cool LED Display
  • More
  • Cancel
Cool LED Display
Blog Slot cars starting lights "from the clouds" v0.1
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Cool LED Display to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: koudelad
  • Date Created: 30 Dec 2017 12:55 PM Date Created
  • Views 3142 views
  • Likes 13 likes
  • Comments 6 comments
  • fsm
  • leddisplaych
  • microchip xpress
  • starting lights
Related
Recommended

Slot cars starting lights "from the clouds" v0.1

koudelad
koudelad
30 Dec 2017

Hello,

 

Let me introduce the sequel of Traffic Light Controller "from the clouds" v0.1 .

 

Idea

One of my coworkers asked me to make starting lights for a slot car race track, which is he going to give his boys for birthdays.

image

 

Being a MotoGP fan, I started the research, what is the procedure to start the race. There is a difference between F1 rules and MotoGP rules and from what I have read, each has their own sequence. (For simplification, I will skip the preparation time etc, as there is no need to follow a 45 minute procedure for the kids to race image.)

F1 uses 5 red lights that are blank at first. Then, are lit one by one to the point where all 5 are on. Then there is a random delay and all the lights go out. This is the moment to start the race.

 

MotoGP start is a bit simpler. Again, all lights are blank at first. Then all the red lights are turned on for a random period between 2 to 5 seconds and the race is started as all the lights go out.

 

Requirements

My goal was to make the lights with the following requirements:

5 red LEDs and a start button is a must. Pushing the start button starts the sequence of a race start (a small delay is needed to have enough time to grab the controller if the driver happens to be a race director at the same time).

Possibility to switch the race procedure from F1 style to MotoGP style.

Random or at least pseudorandom delay for the lights to go out.

 

image

 

Ingredients

  • MPLAB Xpress Evaluation board
  • LEDs - I chose diffused, not too bright (not to make the kids blind after looking directly into the LED) that light sufficiently at cca 3 mA.
  • 5x red LED
  • 5x 470 Ohm resistor for each LED (or more, as noted above)
  • some wires
  • Optionally a battery holder (4x AA / AAA batteries), a single-pole, single-throw switch (SPST), a button, perfboard...
  • MPLAB Xpress Cloud-based IDE - no installation needed (Microchip login needed only to save files), JRE for MPLAB Xpress Code Configurator

 

Hardware

I wrote about the Xpress Evaluation board in my previous blog, so I will just provide a link to the schematics of the board.

As mentioned in requirements, 5 red LEDs, one switch and a push button is required to be connected to the PIC. Oscillator was selected internal low frequency, running at 31 kHz. Here is a simplified schematics with just the external parts connected to the board (one exception is button connected to RA5 and resistor R17, I used them to minimize the number of external components needed).

 

image

 

Software

Development environment

If you want to know more about the MPLAB Xpress Cloud-based IDE, please see my previous blog with my notes on the overall experience, or try it yourself: MPLAB Xpress Cloud-based IDE

After using it for a few more hours, I have to say that this is probably the last project developed in a cloud-based environment. Nothing can compare to the speed and convenience of using a standalone IDE (or just an editor).

 

Program

Now comes the fun part. Traffic Light Controller "from the clouds" v0.1 used a Moore finite-state machine model. The same model is used in this build, but there are now two inputs that need to be considered - an F1 / MotoGP start style switch and a button that initiates the starting sequence. What needs to be changed?

 

The struct that holds all the information for state machine doesn't contain only one nextState variable, but an array of four. Why four? There are two new inputs, each can have two states, that gives four states in total.

Here is how it works. A switch logic state on RB5 is read and a button logic state on RA5 is read. Both bits are stored in the inputSwitches varible in the following way: 0b000000[F1(=1)/MotoGP switch(=0)]|[start button state(1=idle,0=button pressed)].

For each state, all four possible next states are defined, because the input can change anytime. If the input is not important than all four next states can be the same (of unrelated to the meaning of the switch and/or the button). For example all transitions between S_LIGHT1 and S_LIGHT5 are performed this way.

 

The program works this way:

After a power up, nothing is performed for one second. Then one LED (the middle one) is lit for 300 ms just to show that the power is on and the circuit is ready to take orders. The program is now waiting for a start button to be pushed. That is what initiates the starting sequence. After the start button is pushed, nothing happens for 5 seconds. As described above, this is just a small delay for the player who starts the race to grab the controller and get ready. After the five seconds delay a decision is made, based on the state of the F1/MotoGP mode switch. If set to MotoGP, all 5 LEDs are turned. If the switch was set for an F1 mode, the LEDs are lit gradually up to all five. The rest of the process is the same. A pseudo-random delay is made (using an independently counting Timer0, which 5 LSBs were captured when entering the "5 LEDs on state"). There is a base of 2 seconds and additional 0x - 31x (5 bits from Timer0) 100 ms are added. After that period, all LEDs go out and the state gets back to the "waiting for a push of the start button".

 

To get the whole picture, here is a diagram of the state machine with all possible transitions:

 

image

And here comes the source code:

// Starting Lights v0.1
// David Koudela


#include "mcc_generated_files/mcc.h"


// state numbers
#define S_POWER_ON 0
#define S_ACKNOWLEDGE_POWER_ON 1
#define S_WAIT_FOR_START 2
#define S_PRE_START 3
#define S_LIGHT1 4
#define S_LIGHT2 5
#define S_LIGHT3 6
#define S_LIGHT4 7
#define S_LIGHT5 8


// state output values
// LEDs connected to PORTB4:0
#define OUT_NO_LIGHT 0b00000000 // all LEDs off
#define OUT_ACKNOWLEDGE 0b00000100 // one middle LED on
#define OUT_LIGHT1 0b00010000 // 1 LED in sequence is on
#define OUT_LIGHT2 0b00011000 // 2 LEDs in sequence are on
#define OUT_LIGHT3 0b00011100 // 3 LEDs in sequence are on
#define OUT_LIGHT4 0b00011110 // 4 LEDs in sequence are on
#define OUT_LIGHT5 0b00011111 // 5 LEDs in sequence are on


// period definitions in multiplies of 100 ms
#define DELAY_POWER_ON 10 // 1 second
#define DELAY_ACKNOWLEDGE 3 // 300 ms
#define DELAY_PRE_START 50 // 5 seconds
#define DELAY_LIGHT_ON 10 // 1 second
#define DELAY_NONE 0 // 0 ms


// struct for holding the configuration of a state
typedef const struct {
    unsigned char LightsOutput; // output of the current state - saying which LED(s) should be lit
    unsigned char delay; // delay in multiplies of 100 ms; how long a state lasts
    unsigned char nextState[4]; // array of possible next states, will depend on two input values of a switch and a button [F1(=1)/MotoGP switch(=0)]|[start button state(1=idle,0=button pressed)] 
} SLState;


// definition of the state machine for the starting lights
SLState StartingLightFSM[9] = {
    {OUT_NO_LIGHT, DELAY_POWER_ON, {S_ACKNOWLEDGE_POWER_ON, S_ACKNOWLEDGE_POWER_ON, S_ACKNOWLEDGE_POWER_ON, S_ACKNOWLEDGE_POWER_ON} }, // S_POWER_ON
    {OUT_ACKNOWLEDGE, DELAY_ACKNOWLEDGE, {S_WAIT_FOR_START, S_WAIT_FOR_START, S_WAIT_FOR_START, S_WAIT_FOR_START} }, // S_ACKNOWLEDGE_POWER_ON
    {OUT_NO_LIGHT, DELAY_NONE, {S_WAIT_FOR_START, S_PRE_START, S_WAIT_FOR_START, S_PRE_START} }, // S_WAIT_FOR_START
    {OUT_NO_LIGHT, DELAY_PRE_START, {S_LIGHT5, S_LIGHT5, S_LIGHT1, S_LIGHT1} }, // S_PRE_START
    {OUT_LIGHT1, DELAY_LIGHT_ON, {S_LIGHT2, S_LIGHT2, S_LIGHT2, S_LIGHT2} }, // S_LIGHT1
    {OUT_LIGHT2, DELAY_LIGHT_ON, {S_LIGHT3, S_LIGHT3, S_LIGHT3, S_LIGHT3} }, // S_LIGHT2
    {OUT_LIGHT3, DELAY_LIGHT_ON, {S_LIGHT4, S_LIGHT4, S_LIGHT4, S_LIGHT4} }, // S_LIGHT3
    {OUT_LIGHT4, DELAY_LIGHT_ON, {S_LIGHT5, S_LIGHT5, S_LIGHT5, S_LIGHT5} }, // S_LIGHT4
    {OUT_LIGHT5, 30, {S_WAIT_FOR_START, S_WAIT_FOR_START, S_WAIT_FOR_START, S_WAIT_FOR_START} } // S_LIGHT5
};


// variable to hold the current state
unsigned char currentState;
// variable to hold the state of two input values - a switch and a button
unsigned char inputSwitches;
// variable to create a longer delay in multiplies of 100 ms
unsigned char delay100ms;


/*
                         Main application
 */
void main(void)
{
    // initialize the device - pins, an oscillator and Timer0
    SYSTEM_Initialize();
    
    // set the state in wich the FSM starts
    currentState = S_POWER_ON;


    // endless loop
    while (1)
    {
        // output a LED pattern of a current state to PORTB latch
        LATB = StartingLightFSM[currentState].LightsOutput;
        
        // assign the delay value (in multiplies of 100 ms) from FSM definition to the delay variable
        // the only exception is the final state with 5 LEDs on, where the delay is random, 2 - 5 seconds long
        // pseudorandom element is introduced by reading 5 LSBs of Timer0 (running at 31 kHz)
        if (currentState == S_LIGHT5) {
            delay100ms = TMR0L;
            delay100ms &= 0b00011111;
            delay100ms += 20u;
        } else {
            delay100ms = StartingLightFSM[currentState].delay;   
        }
        
        // delay for a desired number of 100 ms
        // embedded delay library can have problem with generating longer delays at higher frequencies  
        for (delay100ms; delay100ms > 0; delay100ms-- ) {  
            __delay_ms(100u);  
        } 
        
        
        // the following code reads state of the F1 / MotoGP start style switch and state of the start button
        // only two LSBs of inputSwitches variable are used:
        // 0b000000[F1(=1)/MotoGP switch(=0)]|[start button state(1=idle,0=button pressed)] 
        
        // read the F1 / MotoGP switch value, place the value in bit 1 of inputSwitches
        // and mask all other bits so they are not affected
        if (IO_SW_F1_MGP_GetValue()) { inputSwitches |= 0b00000010; }
            else { inputSwitches &= 0b11111101; }


        // read the start button value, place the value in bit 0 of inputSwitches
        // and mask all other bits so they are not affected
        if (IO_BTN_START_GetValue()) { inputSwitches &= 0b11111110; }
            else { inputSwitches |= 0b00000001; }
        
        // determine the next state from the current state and combination of input (switch and 
        currentState = StartingLightFSM[currentState].nextState[inputSwitches];
            
    }
}
/**
 End of File
*/

 

Video

Here is a video proof of work. We don't have slot cars race track at home, so I tested the lights with model cars. Both videos start with plugging in the USB to a computer (off the camera).

Please excuse that it is not a finished product yet.

 

F1 style start:

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

PS: I had a model of an F1 car, but it drove off the table during test run to the area I can't access without moving a wardrobe and the table image

 

MotoGP style start:

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

What to do next

Some ideas are:

1) Make this a finished product, place the LEDs on some pillar etc.

2) Embed a siren for signaling periods before starting the countdown (for real races, there are sirens for the crew to get out of the racing track, 3 and one minutes before the warm-up lap etc.). Only if this doesn't make the parents crazy, of course image

3) Add sensors for jump-start detection: probably optical for each lane. After adding these, some new possibilities open, for example a lap timer.

 

What do you think? Is there anything that you would do differently?

 

Thank you for reading and watching.

 

David

Attachments:
StartingLights.zip
  • Sign in to reply

Top Comments

  • mcb1
    mcb1 over 7 years ago +4
    Excellent.work. This kid will be the envy of all his mates, inc those with a track of their own. Mark
  • jw0752
    jw0752 over 7 years ago +3
    Hi David, Your project shows the excellent results that are possible when one puts in the time to properly research and plan a project. Great Job! John
  • fmilburn
    fmilburn over 7 years ago +3
    Great writeup and description of project!
  • DAB
    DAB over 7 years ago

    Nice post.

     

    I spent a lot of time with slot cars of various sizes.

    Lots of fun.

     

    DAB

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • genebren
    genebren over 7 years ago

    What a fun little project! I really enjoyed your use of a state-machine to control the light sequence. Well done!

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • fmilburn
    fmilburn over 7 years ago

    Great writeup and description of project!

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • koudelad
    koudelad over 7 years ago in reply to jw0752

    Thank you both for your kind comments.

     

    I am an analyst and observer by heart. And I work as a software analyst (not related to electronics at all), basically someone, who can talk to both business users, who need something to be implemented, and a developer, who knows how to implement it. One might say it is a redundant position (which kind of is, especially in smaller companies), but only up to the point where the business user can't have a discussion with the developer directly. Both roles have their own perspective, needs, language, tools etc. Many of you probably know, what happens when some things are implemented in a way that no one wants, but the essential things are missing.

     

    In my free time (I mean free time for hobbies like electronics), it is a great relief to do a mini project with all the development steps (some might say that waterfall approach is old-school - including most people at my work). Proper analysis (at least of the most important parts) saves huge amount of time during implementation and testing. Although I try to experiment more to fail more (to hopefully learn more image ), I don't know a worse feeling than finding out at 95 % of completion that it is necessary to start all over, because something obvious was skipped in the beginning (with none or insufficient analysis).

     

    David

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jw0752
    jw0752 over 7 years ago

    Hi David,

    Your project shows the excellent results that are possible when one puts in the time to properly research and plan a project. Great Job!

    John

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube