In respect of using belts etc I am extremely constrained by the size of the model. This is what I am working with…
-
Thanks for the connection diagram.
-
Motors powered by the Arduino 5v pin is ill advised.
Your Arduino board 5 volt supply is not adequate to power your project.
If you do use it as such, your Arduino may be damaged.
Also, never connect an inductive load to the Arduino 5v pin. -
Here is some homework for you.
- FYI, If you will be making your own belts, the glue (available on Amazon) is great !
Search for Oil Glue.
Then use the stepper to drive the outside of the turn table and get a similar reduction in movement.
Thank you LarryD. I have saved that glue to my Amazon basket just in case. I have also watched that video, which was very helpful indeed. I will be spending some time perusing his website for some more guidance. I especially like how he explains his sketches.
-
Please confirm your rotary encoder has a push switch, i.e. pushing on the shaft closes an internal switch.
-
Test time, do you know what a:
-pull-up/pull-down resistor is ?
-non-blocking TIMER is ? (based on millis( ) ).
-State Machine is ?
-bouncing switch is ? -
How do you envision the IR slot sensor will be used ?
-
Show us images of previous projects.
-
Have you considered using an OLED display ?
Example: SSH1106 (1.3”)
Yes my rotary encoder has a push switch.
I will answer as best I can from my understanding. Apologies for any incorrect terminology I’ve quickly learnt that this is very very complex.
The pull-up/down refers to either being connected directly to vcc (up) or ground (down). They are used to control the state of an input pin. I.e. high or low. The theory is that this ensures the Arduino (in this case) always has either a high or low state on the pin. - I think that’s all correct anyway.
I wouldn’t know how to work out the correct value to use though as I haven’t personally used them before.
The blocking timer, as my understanding goes - but feel free to correct me, is to do with whether a time delay affects the entire Arduino. For instance whilst completing the time of, say, 10 seconds it means all other processes also get blocked from occurring for those 10 seconds.
A state machine is the process of determining whether a pin is high or low from an input. It’s the process of taking, for instance, a push to make switch, being recognised and turning a low state to high etc.
A bouncing switch refers to the noise created when a physical switch is thrown. Due to the mechanics of the parts moving this can cause multiple high/low user inputs to be registered as the pins physically switch and bounce or chatter between contacts.
I envisaged using the IR sensor to determine zero when the beam is broken. Obviously I am extremely limited due to the size of the model so I was intending to attach something to a gear/disc mounted underneath but on the same motor shaft. Thereby it would directly represent the movement of the turntable above it. However. I am open to ideas that would be better. I was intending to test different options once I knew the code worked so that I could test in the real world. I am much more hands on and prefer to physically see things to help me overcome problems.
I have not considered using an oled screen but would be happy to do so.
My thinking was I am trying to build the layout for my autistic son and so I wanted it to be very easy to use for him.
I was going to hide the rotary encoder and delete/set location switch in the layout so only I could access it.
That way he could only press cw or ccw to determine which direction he wanted to move in and/or to complete a half turn. I also determined that the zero routine needed to be accessible from the main controller in the event of power loss etc prior to writing the known location to the EEPROM.
For what purpose would you use the screen for? The one you show is quite small in size so I could easily integrate it into a controller if needed.
My previous projects are all related to applications such as the MERG DCC system, making moving scenery on layouts/dioramas - for instance I have created a moving canal boat system for this layout from a bike chain and magnets, creating voltage regulators and controllers for dc layouts etc. I also have spent time restoring and renovating old game consoles - gameboys, Lynx, sega’s etc. I have not done any programming like this before.
My previous projects for the Arduino are entirely related to getting this working - testing sensors, inputs, etc. It is all for the purpose of creating this turntable for my son.
I forgot to mention. I was considering the use of the ir sensor over a hall effect sensor for two reasons. (1) at this scale it would prove extremely inaccurate as the magnet would never travel very far from the sensor. (2) the train wheels are magnetic to keep them on the rails. A magnet could therefore theoretically affect this.
-
If you are willing to hang in there, we can help you through your project.
-
This will require you to ask questions when you do not understand something.
-
Unless somebody else wants to take over, I can start this process.
-
Do you want to commit the time into this ?
Without a doubt.
-
Okay then let's go.
-
Below is a schematic for the following Arduino UNO sketch.
-
I start projects off by using a skeleton sketch as it saves a lot of typing and time.
See the below sketch. -
This sketch toggles a Hearbeat LED every 500ms.
We use a Heartbeat LED to see if the code is executing and can tell if it is in never never land if the LED stops flashing or stutters. -
When the switch is closed a testLED turns on for a period of time then goes out.
-
When the switch is closed we save the current time and when we let go of the switch, we print the time to the serial monitor that the switch was closed/pressed.
- See if you can work your way through the sketch, ask questions . . . .
//================================================^================================================
//
// URL
//
// Name
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 24/05/25 Started writing this sketch
//
//
//
//#include <Wire.h>
//================================================
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define CLOSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define OPENED HIGH
//================================================^================================================
// millis() / micros() B a s e d T I M E R S
//================================================^================================================
//To keep the sketch tidy, you can put this structure in a different tab in the IDE
//
//These TIMER objects are non-blocking
struct makeTIMER
{
#define MILLIS 1
#define MICROS 1000 //we can use this value to divide into a variable to get milliseconds
#define ENABLED true
#define DISABLED false
#define YES true
#define NO false
#define STILLtiming 0
#define EXPIRED 1
#define TIMERdisabled 2
//these are the bare minimum "members" needed when defining a TIMER
int TimerType; //what kind of TIMER is this? MILLIS/MICROS
unsigned long Time; //when the TIMER started
unsigned long Interval; //delay time which we are looking for
bool TimerFlag; //is the TIMER enabled ? ENABLED/DISABLED
bool Restart; //do we restart this TIMER ? YES/NO
//================================================
//condition returned: STILLtiming (0), EXPIRED (1) or TIMERdisabled (2)
//function to check the state of our TIMER ex: if(myTimer.checkTIMER() == EXPIRED);
byte checkTIMER()
{
//========================
//is this TIMER enabled ?
if (TimerFlag == ENABLED)
{
//========================
//has this TIMER expired ?
if (getTime() - Time >= Interval)
{
//========================
//should this TIMER restart again?
if (Restart == YES)
{
//restart this TIMER
Time = getTime();
}
//this TIMER has expired
return EXPIRED;
}
//========================
else
{
//this TIMER has not expired
return STILLtiming;
}
} //END of if (TimerFlag == ENABLED)
//========================
else
{
//this TIMER is disabled
return TIMERdisabled;
}
} //END of checkTime()
//================================================
//function to enable and restart this TIMER ex: myTimer.enableRestartTIMER();
void enableRestartTIMER()
{
TimerFlag = ENABLED;
//restart this TIMER
Time = getTime();
} //END of enableRestartTIMER()
//================================================
//function to disable this TIMER ex: myTimer.disableTIMER();
void disableTIMER()
{
TimerFlag = DISABLED;
} //END of disableTIMER()
//================================================
//function to restart this TIMER ex: myTimer.restartTIMER();
void restartTIMER()
{
Time = getTime();
} //END of restartTIMER()
//================================================
//function to force this TIMER to expire ex: myTimer.expireTimer();
void expireTimer()
{
//force this TIMER to expire
Time = getTime() - Interval;
} //END of expireTimer()
//================================================
//function to set the Interval for this TIMER ex: myTimer.setInterval(100);
void setInterval(unsigned long value)
{
//set the Interval
Interval = value;
} //END of setInterval()
//================================================
//function to return the current time
unsigned long getTime()
{
//return the time i.e. millis() or micros()
//========================
if (TimerType == MILLIS)
{
return millis();
}
//========================
else
{
return micros();
}
} //END of getTime()
}; //END of struct makeTIMER
// D e f i n e a l l a r e T I M E R S
//================================================^================================================
/*example
//========================
makeTIMER toggleLED =
{
MILLIS/MICROS, 0, 500ul, ENABLED/DISABLED, YES/NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
Function examples:
toggleLED.checkTIMER();
toggleLED.enableRestartTIMER();
toggleLED.disableTIMER();
toggleLED.expireTimer();
toggleLED.setInterval(100ul);
*/
//========================
makeTIMER heartbeatTIMER =
{
MILLIS, 0, 500ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER switchesTIMER =
{
MILLIS, 0, 5ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER machineTIMER =
{
MICROS, 0, 1000ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER commonTIMER =
{
MILLIS, 0, 1000ul, DISABLED, NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
// S t a t e M a c h i n e
//================================================^================================================
//the States in our machine (use better names that mean something to you)
enum STATES : byte
{
STARTUP, STATE1, STATE2, STATE3, STATE4, FINISHED
};
STATES mState = STARTUP;
// G P I O s
//================================================^================================================
//
//structure to define input objects
struct makeInput
{
const byte pin; //the digital input pin number
unsigned long switchTime; //the time the switch was closed
byte lastState; //the state the input was last in
byte counter; //a counter used to valididate a switch change in state
}; //END of struct makeInput
//Digital Inputs
//===================================
//define this input which is connected to a PB switch
makeInput mySwitch =
{
2, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
byte filter = 10;
//TIMER "switches" runs every 5ms.
//5ms * 10 = 50ms is needed to validate a switch change in state.
//A switch change in state is valid "only after" 10 identical changes is detected.
//used to filter out EMI noise in the system
//OUTPUTS
//===================================
const byte testLED = 12;
const byte heartbeatLED = 13;
//VARIABLES
//===================================
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
//Serial.begin(9600);
//use INPUT_PULLUP so the pin dose not float which can cause faulty readings
pinMode(mySwitch.pin, INPUT_PULLUP);
pinMode(heartbeatLED, OUTPUT);
digitalWrite(testLED, LEDoff);
pinMode(testLED, OUTPUT);
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//======================================================================== T I M E R heartbeatLED
//is it time to toggle the heartbeat LED ?
if (heartbeatTIMER.checkTIMER() == EXPIRED)
{
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R switches
//is it time to check our switches ?
if (switchesTIMER.checkTIMER() == EXPIRED)
{
checkSwitches();
}
//======================================================================== T I M E R machine
//is it time to service our State Machine ?
if (machineTIMER.checkTIMER() == EXPIRED)
{
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
}
break;
//========================
case STATE1:
{
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
if (commonTIMER.checkTIMER() == EXPIRED)
{
digitalWrite(testLED, LEDoff);
//we are finished with this TIMER
commonTIMER.disableTIMER();
//next state
mState = STATE2;
}
}
break;
//========================
case STATE2:
{
//Do something
}
break;
//========================
case STATE3:
{
//Do something
}
break;
//========================
case STATE4:
{
//Do something
}
break;
//========================
case FINISHED:
{
//Do something
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte pinState;
//======================================================================== mySwitch.pin
pinState = digitalRead(mySwitch.pin);
//===================================
//has this switch changed state ?
if (mySwitch.lastState != pinState)
{
mySwitch.counter++;
//is this change in state stable ?
if (mySwitch.counter >= filter)
{
//get ready for the next sequence
mySwitch.counter = 0;
//update to this new state
mySwitch.lastState = pinState;
//========================
//did this switch go closed ?
if (pinState == CLOSED)
{
//the time this switch closed
mySwitch.switchTime = millis();
digitalWrite(testLED, LEDon);
//set interval to 2 seconds
commonTIMER.setInterval(2000ul);
commonTIMER.enableRestartTIMER();
//next state
mState = STATE1;
}
//========================
//did this switch go opened ?
else if (pinState == OPENED)
{
Serial.print("The time the switch was closed = ");
Serial.println(millis() - mySwitch.switchTime);
}
}
}
//===================================
//a valid switch change has not been confirmed
else
{
mySwitch.counter = 0;
}
//END of mySwitch.pin
//======================================================================== Next Switch
} //END of checkSwitches()
//================================================^================================================
OK i have read through and implemented the code onto my uno.
The circuit works successfully with the heartbeat led flashing in time with the yellow L led on the uno board itself. The momentary switch triggers the test led. even if i hold the switch down it still times the set amount and switches off. it will not come back on until i release the switch and press it again. the heartbeat led flash remains constant throughout.
Q1 - the internal pull up resistor and pin on your schematic.
is this prebuilt into the 5v pin? it states 20-50k, does the user need to determine this value, or does it change automatically based on if the pin is high or low state? is there a physical pin so i can test its state?
Q2 - can you please clarify for me what bool is? i can see it is used to refer to whether the timer is enabled or not, and then whether the restart should occur or not. i presume therefore that it relates to the decision making process.
Q3 - where is the getTime defined? is this the time = getTime(); of the restartTIMER section?
I believe the 'if' or 'else' refers to the state machine. decision making process.
The 'return' is the final piece of code that is fed back into the machine. that way it avoids the constant feed of misinformation. by feeding back just the last piece of information it allows for a more stable feedback.
Q4 - I am not getting a time stamp on the serial monitor just some square shapes. i cannot locate what baud i should be in from the code. is this defined somewhere? i thought this needed to be done.
the 5ms * 10 ensures that a constant reading from the user input must be received for 10 consequetive sequences. this is to irradicate/allow for switch bounce. being that this is only 50ms the user is unlikely to even notice it occurs.
Q5 - what is the serial.begin(115200) and (9600) ? Does this relate to my previous question on the serial monitor baud.
is my understanding correct that when i haven't released the push button the reason that the light doesn't remain lit, or light again is due to the else if pinstate==opened code? whereby if it is closed it should then print the time closed to the serial monitor, and end the checkswitches routine.
is that correct?
Thank you for this. i am very appreciative.
ok i have answered my own questions in that my turning my serial monitor to 115200 baud i am now getting time stamps correctly
Which I shall bookmark and use as an example. For ppl we ask to draw schematic, and they're all what software should I get…
pencil and paper.
a7
Hi a7. i think thats a complement - im going to take it as one anyway. im feeling extremely silly on here at the moment. just treading water to stay afloat i think. I am already aware that the drawing is flawed. in that i know i need a separate power supply for the stepper motor driver, and, that i likely need pull-up/down resistors on my input pins. but its still a work in progress. As far as im concerned its pencil and paper over software every day of the week lol.
Q1 - the internal pull up resistor and pin on your schematic.
is this prebuilt into the 5v pin? it states 20-50k, does the user need to determine this value, or does it change automatically based on if the pin is high or low state? is there a physical pin so i can test its state?
- There is an internal pull-up resistor on all GPIO pins, can be 20k to 50k.
You do not need to worry what the value is, just that you can enable it.
No pin to test it.
Q2 - can you please clarify for me what bool is? i can see it is used to refer to whether the timer is enabled or not, and then whether the restart should occur or not. i presume therefore that it relates to the decision making process.
- bool stands for Boolean.
When we create a variable we must assign the varriable a number type.
Number 'type's.
- boolean (8 bit) - simple logical true/false, Arduino does not use single bits for bool
- byte (8 bit) - unsigned number from 0 to 255
- char (8 bit) - signed number from -128 to 127. The compiler will attempt to interpret this data type as a character in some circumstances, which may yield unexpected results
- unsigned char (8 bit) - same as 'byte'; if this is what you're after, you should use 'byte' instead, for reasons of clarity
- word (16 bit) - unsigned number from 0 to 65535
- unsigned int (16 bit)- the same as 'word'. Use 'word' instead for clarity and brevity
- int (16 bit) - signed number from -32768 to 32767. This is most commonly what you see used for general purpose variables in Arduino example code provided with the IDE
- unsigned long (32 bit) - unsigned number from 0 to 4,294,967,295. The most common usage of this is to store the result of the millis() function, which returns the number of milliseconds the current code has been running
- long (32 bit) - signed number from -2,147,483,648 to 2,147,483,647
- float (32 bit) - signed number from -3.4028235E38 to 3.4028235E38. Floating point on the Arduino is not native; the compiler has to jump through hoops to make it work. If you can avoid it, you should. We'll touch on this later. Sparkfun.
- You select the 'type' best suited for your variables.
Examples:
- your variable does not change and it defines a pin on the Arduino. const byte limitSwitchPin = 34;
- since an analog variable can be 0 to 1023, a byte will not do, you can select 'int'. int temperature;
- if your variable needs to be within -64 to +64 a 'char' will do nicely. char joystick;
- if your variable is used for ASCII then you need type 'char',
char myText[ ] = "Raspberry Pie Smells";
- if your variable enables some code then boolean can be used. boolean enableFlag = false;
- millis() returns the time in ms since rebooting, unsigned long currentTime = millis();
etc.
Q3 - where is the getTime defined? is this the time = getTime(); of the restartTIMER section?
- There is a function we can access called millis().
This function returns the time in millis seconds since the Arduino was powered up (turned on).
I believe the 'if' or 'else' refers to the state machine. decision making process.
The 'return' is the final piece of code that is fed back into the machine. that way it avoids the constant feed of misinformation. by feeding back just the last piece of information it allows for a more stable feedback.
- Not sure what you are saying.
if( . . .) and else if(. . .) are decision statements we can use to determine when something has met a certain criteria; when it has we can do something.
These statements can be used in a State Machine but elsewhere also.
Q4 - I am not getting a time stamp on the serial monitor just some square shapes. i cannot locate what baud i should be in from the code. is this defined somewhere? i thought this needed to be done.
- In the setup( ) function you will find this Serial.begin(115200);
It sets the speed to 115200 baud; your Serial Monitor must also be set to this value before you can see the correct text.
Look in the bottom right corner of the Serial Monitor window.
the 5ms * 10 ensures that a constant reading from the user input must be received for 10 consequetive sequences. this is to irradicate/allow for switch bounce. being that this is only 50ms the user is unlikely to even notice it occurs.
- This is just one method we can use to make sure switch bounce OR electrical noise has not cause a change in the switch state.
In this case, the time is set to 5 * 10ms = 50ms before we validate a change in switch state.
Q5 - what is the serial.begin(115200) and (9600) ? Does this relate to my previous question on the serial monitor baud.
- Yes, if you look at the baud rates in the bottom of the Serial Monitor window, you can see all the baud rates you an use.
is my understanding correct that when i haven't released the push button the reason that the light doesn't remain lit, or light again is due to the else if pinstate==opened code? whereby if it is closed it should then print the time closed to the serial monitor, and end the checkswitches routine.
- When you close the switch on GPIO pin 2 the code starts a TIMER and turns on the LED on pin 12 (for 2 seconds), when this TIMER expires, the code stops this TIMER and turns off the LED.
When it comes to switches it is highly recommended we look for switch changes in state (as this code does).
The LED is totally managed by the TIMER for pin 12, not when the switch is held or opened.
Here is a schematic of your proposed projects.
Please check it over to see if it meets you design.
EDIT, updated schematic
Thank you for clearing up that 'types' definitions. i have saved that for future reference.
Wow! Yes, that schematic would work perfectly for my needs. It takes into account the separate motor power supply.
Ive also noted from your comments to my questions that the internal pull up resistors are built in for the relevant pins. hence why they are not shown/needed.
what does the input Z = 100Meg relate too?
I also note that the heartbeat sensor is integrated also to show the user the system is active.
How would i power the Arduino using this method? can it be powered from the same external power supply as the motor or would i need a separate one.
The reason i ask as i dont want to have it connected to my pc at all times.
The scale of trains i am modeling run on 5v so i intended on intercepting the power supply prior to it hitting the PWM track controllers. I presume i could still do this?
Ive also noted from your comments to my questions that the internal pull up resistors are built in for the relevant pins. hence why they are not shown/needed.
- Some times we need to use an EXTERNAL pull-up OR pull-down resistor on digital pin in our projects.
The maker of the 328 controller has give us the ability to use a built in pull_up resistor which we can enable, the 20-50k might be too large in some applications.
We some times do not even need a pull_up.
what does the input Z = 100Meg relate too?
- The GPIO pins have an impedance of over 100meg ohms to the outside world (devices connected to the pins).
If we were to measure this with an ohm meter (don't do this) we would see 100M ohms or more on our meter.
I also note that the heartbeat sensor is integrated also to show the user the system is active.
- I always us a Heartbeat LED on projects as it helps show if things are working.
In the end, this LED can be removed/not used.
How would i power the Arduino using this method? can it be powered from the same external power supply as the motor or would i need a separate one.
- You can power the Arduino for the external 5v power supply, often we make up a power only USB cable and plug the cable into the external supply.
The reason i ask as i dont want to have it connected to my pc at all times.
The scale of trains i am modeling run on 5v so i intended on intercepting the power supply prior to it hitting the PWM track controllers. I presume i could still do this?
- Yes you can, however, be aware if there is electrical noise on that power supply due to the train motor it might interfere with the Arduino.
Test time:
- How would you make the Heartbeat LED toggle every 1 second ?
- How would you make it so the LED on pin 12 is ON all the time and go OFF for 2 seconds when the switch on pin 2 is closed ?
Yes. And I hadn't looked closely, one more thing that helps is to include all sources of power and how it is delivered to the components that need it, LEDs to motors.
But srsly, totally a compliment.
a7
Right what i first thought was correct i have just checked and it didn't work as intended. im just checking it over again now.