Servo Controlled Points (Ringbalin)

 

Ringbalin PICAXE Point Control System

Overview

Each point is controlled by a small distributed system made up of three parts:

  1. PICAXE 08M2 point board - the controller

  2. Input conditioning board - cleans up the button and switch signals

  3. Calibration box - a portable tool for setting the servo end positions

The system reads the physical point lever, moves a servo to throw the point, and reports the point's state to an ESP-01, which publishes it over MQTT.

The PICAXE 08M2 Point Controller Circuit

Each point has its own PICAXE 08M2 board, which does three jobs:

  1. Reads the physical point lever switch

  2. Drives the servo to move the point blades

  3. Reports the point's state to the ESP-01 so it can be sent over the network

Pin connections

Pin 1 +5V supply 

Pin 2 (C.5) Calibration Enable - held LOW by a 10K pulldown in normal use; +5V applied when the calibrator box is switched ON

Pin 3 (C.3) Point lever switch input

Pin 4 (C.2) Servo control signal

Pin 5 (C.1) Calibrator UP button input

Pin 6 (C.4) Calibrator DOWN button input

Pin 7 (C.0) Digital status output to ESP-01 (through a 12K/22K divider)

Pin 8 0V ground

Normal operation

  • The PICAXE constantly monitors the point lever on C.3.

  • When the lever changes, the PICAXE reads the stored servo positions from its EEPROM and drives the servo on C.2.

  • At the same time it sets C.0 HIGH (thrown) or LOW (normal).

  • This simple digital level is reduced from 5V to 3.3V by the R1/R2 divider and fed to the ESP-01 RX pin. The ESP-01 then publishes an MQTT message.

Power

  • The servo is powered separately at 5V (not through the PICAXE board).

  • The servo signal comes from C.2.

  • All grounds are common.

The Input Conditioning Board

The conditioning board sits between the PICAXE point board and the calibrator box. It has two jobs:

  • Cleaning up the point lever switch signal

  • Cleaning up the calibrator button signals

The calibrator box plugs into the conditioning board via a D9 socket, and the conditioning board is wired back to the PICAXE point board by a wire loom.

The conditioning board is a retrofit that was required because calibration of blade positions was originally done by potentiometers outputting a voltage that set the servo position. This proved to be unworkable as the voltage could not be adjusted to be accurate enough to perform the job. This led to servos over-driving risking damage and causing brown outs of their power supply.

Switch input (C.3)

  • A 10K pulldown resistor holds the input LOW until the point lever switch closes.

Button inputs (C.1 and C.4)

Each button channel has:

  • a 10K pull-up to 5V (input held HIGH when idle)

  • a 1K series resistor

  • a 47nF capacitor to ground (debounce)

When a button is pressed, the input is pulled LOW cleanly, and the PICAXE reads it without bounce or noise.

Connections

  • Calibrator box -> D9 socket on the conditioning board

  • Conditioning board -> PICAXE point board (via wire loom)

  • Loom carries: 5V, C.5 (enable), C.1 (UP), C.4 (DOWN), GND

  1. The Calibration Box Operation

The calibrator is a small portable box used to set the servo end positions for each point. It plugs into the conditioning board.

What's in the box

  • Toggle switch - enables calibration mode

  • LED - lights when calibration mode is ON

  • UP momentary button

  • DOWN momentary button

  • D9 plug for connection to each point's conditioning board

Calibration sequence

  1. Plug in the calibrator with the toggle switch OFF.

  2. Turn toggle ON - the LED lights and +5V is applied to C.5, putting the PICAXE into calibration mode.

  3. Set the point lever to NORMAL.

  4. Trim with UP/DOWN until the blade sits correctly against the stock rail.

  5. Turn toggle OFF - this automatically saves the NORMAL position to EEPROM.

  6. Turn toggle ON again.

  7. Set the point lever to THROWN.

  8. Trim with UP/DOWN until that blade sits correctly.

  9. Turn toggle OFF - this automatically saves the THROWN position to EEPROM.

  10. Unplug the calibrator and move to the next point.

Key points

  • The point lever (C.3) selects which end (NORMAL or THROWN) is being calibrated.

  • The UP/DOWN buttons trim the servo position in small steps.

  • Turning the box OFF saves automatically - there is no separate SAVE button.

  • The ESP-01 status link is unchanged during calibration; it simply continues reporting the point's state.

Summary of the signal chain

Physical point lever -> PICAXE (C.3) -> servo moves the blades

Servo state -> PICAXE (C.0) -> R1/R2 divider -> ESP-01 RX -> MQTT -> Pi GUI

Calibration -> Calibrator box -> conditioning board -> PICAXE (C.1/C.4/C.5) -> EEPROM

The Picaxe Program Code

' Ringbalin Point Controller - Plug-in Calibrator
' PICAXE 08M2
'
' Normal operation:
' C.3 point lever controls the servo.
'
' Calibration operation:
' C.5 HIGH = calibrator enabled.
' C.1 LOW = UP button pressed.
' C.4 LOW = DOWN button pressed.
' Point lever selects NORMAL or THROWN.
' Short button press = one fine adjustment.
' Button held = repeated coarse adjustments.
' Turning calibrator OFF saves the selected position.
'
' Important:
' Calibrator must be OFF when the PICAXE is powered up
' or reset. C.5 must be LOW during startup.

#picaxe 08m2
#no_data
setfreq m4

' ============================================================
' PIN DEFINITIONS
' ============================================================

symbol switchPin = pinC.3 ' Point lever switch
symbol upBtn = pinC.1 ' Conditioned UP input
symbol downBtn = pinC.4 ' Conditioned DOWN input
symbol calibEn = pinC.5 ' Calibrator enable; HIGH = ON

symbol servoPin = C.2 ' Servo signal
symbol esp01Pin = C.0 ' Status output to ESP-01

' ============================================================
' VARIABLES
' ============================================================

symbol servoPosition = b4
symbol normalPos = b5
symbol thrownPos = b6
symbol calibrationTarget = b7
symbol holdCount = b8

' ============================================================
' EEPROM ADDRESSES
' ============================================================

symbol EEPROM_NORMAL = 0
symbol EEPROM_THROWN = 1

' ============================================================
' SERVO LIMITS
' PICAXE recommends approximately 75 to 225
' ============================================================

symbol SERVO_MIN = 75
symbol SERVO_MAX = 225

' ============================================================
' COARSE ADJUSTMENT SETTINGS
' ============================================================

symbol COARSE_STEP = 5

' 15 x approximately 20 ms = approximately 300 ms
symbol HOLD_TICKS = 15

' Limits used to prevent coarse steps exceeding the servo range
symbol COARSE_UP_LIMIT = 220
symbol COARSE_DOWN_LIMIT = 80

' ============================================================
' INITIALISATION
' ============================================================

init:
' C.5 must be LOW when the PICAXE starts.
' The calibrator must be OFF during power-up or reset.

' After this command C.5 can safely be used as an input.
disconnect

' Load saved servo positions from EEPROM
read EEPROM_NORMAL, normalPos
read EEPROM_THROWN, thrownPos

' --------------------------------------------------------
' Check NORMAL position.
'
' This handles:
' - an erased EEPROM value of 255
' - an EEPROM value of 0
' - any value outside the usable servo range
'
' Existing valid values between 75 and 225 are preserved.
' --------------------------------------------------------

if normalPos < SERVO_MIN then
normalPos = 75
write EEPROM_NORMAL, normalPos
endif

if normalPos > SERVO_MAX then
normalPos = 75
write EEPROM_NORMAL, normalPos
endif

' --------------------------------------------------------
' Check THROWN position.
' --------------------------------------------------------

if thrownPos < SERVO_MIN then
thrownPos = 175
write EEPROM_THROWN, thrownPos
endif

if thrownPos > SERVO_MAX then
thrownPos = 175
write EEPROM_THROWN, thrownPos
endif

' --------------------------------------------------------
' Start the servo at the saved position selected by
' the physical point lever.
' --------------------------------------------------------

if switchPin = 1 then
servoPosition = thrownPos
high esp01Pin
else
servoPosition = normalPos
low esp01Pin
endif

servo servoPin, servoPosition
pause 1000

' ============================================================
' MAIN PROGRAM LOOP
' ============================================================

main:
' --------------------------------------------------------
' Check whether the calibrator has been enabled.
' Confirm HIGH after 20 ms to reject switch bounce.
' --------------------------------------------------------

if calibEn = 1 then
pause 20

if calibEn = 1 then
gosub calibration
endif
endif

' --------------------------------------------------------
' NORMAL OPERATION
' The calibration buttons are ignored here.
' --------------------------------------------------------

if switchPin = 1 then
servoPosition = thrownPos
high esp01Pin
else
servoPosition = normalPos
low esp01Pin
endif

servopos servoPin, servoPosition
pause 50

goto main

' ============================================================
' CALIBRATION MODE
' ============================================================

calibration:
' Select the initial calibration position from the lever.
' The lever selects which value is being adjusted.
' It does not directly control the servo while calibrating.

if switchPin = 1 then
calibrationTarget = 1
servoPosition = thrownPos
else
calibrationTarget = 0
servoPosition = normalPos
endif

servopos servoPin, servoPosition
pause 100

calibration_loop:
' --------------------------------------------------------
' Check whether the calibrator has been switched OFF.
' Confirm LOW after 20 ms.
' --------------------------------------------------------

if calibEn = 0 then
pause 20

if calibEn = 0 then
gosub save_current_position
pause 200
return
endif
endif

' --------------------------------------------------------
' Allow the lever to select NORMAL or THROWN while
' calibration remains enabled.
'
' The previous adjustment is saved before changing target.
' --------------------------------------------------------

if calibrationTarget = 0 then

' Change from NORMAL adjustment to THROWN adjustment
if switchPin = 1 then
normalPos = servoPosition
write EEPROM_NORMAL, normalPos

calibrationTarget = 1
servoPosition = thrownPos

servopos servoPin, servoPosition
pause 100
endif

else

' Change from THROWN adjustment to NORMAL adjustment
if switchPin = 0 then
thrownPos = servoPosition
write EEPROM_THROWN, thrownPos

calibrationTarget = 0
servoPosition = normalPos

servopos servoPin, servoPosition
pause 100
endif

endif

' --------------------------------------------------------
' Check the calibrator buttons.
' Both buttons are active LOW.
' --------------------------------------------------------

if upBtn = 0 then
gosub handle_up
endif

if downBtn = 0 then
gosub handle_down
endif

pause 10
goto calibration_loop

' ============================================================
' SAVE CURRENT CALIBRATION POSITION
' ============================================================

save_current_position:
if calibrationTarget = 1 then
thrownPos = servoPosition
write EEPROM_THROWN, thrownPos
else
normalPos = servoPosition
write EEPROM_NORMAL, normalPos
endif

return

' ============================================================
' UP BUTTON HANDLER
'
' Short press:
' One fine step.
'
' Held button:
' After approximately 300 ms, repeated coarse steps.
' ============================================================

handle_up:
' Initial software debounce
pause 20

' Ignore a brief noise pulse
if upBtn = 1 then
return
endif

holdCount = 0

up_held:
' Check whether the button has been released
if upBtn = 1 then
pause 20

' Confirm release
if upBtn = 1 then

' Short press gives one fine step
if holdCount < HOLD_TICKS then
gosub fine_up
endif

return
endif
endif

' Count the duration of the button press
if holdCount < HOLD_TICKS then
holdCount = holdCount + 1
pause 20
else
' Long press gives repeated coarse steps
gosub coarse_up
pause 100
endif

goto up_held

' ============================================================
' DOWN BUTTON HANDLER
'
' Short press:
' One fine step.
'
' Held button:
' After approximately 300 ms, repeated coarse steps.
' ============================================================

handle_down:
' Initial software debounce
pause 20

' Ignore a brief noise pulse
if downBtn = 1 then
return
endif

holdCount = 0

down_held:
' Check whether the button has been released
if downBtn = 1 then
pause 20

' Confirm release
if downBtn = 1 then

' Short press gives one fine step
if holdCount < HOLD_TICKS then
gosub fine_down
endif

return
endif
endif

' Count the duration of the button press
if holdCount < HOLD_TICKS then
holdCount = holdCount + 1
pause 20
else
' Long press gives repeated coarse steps
gosub coarse_down
pause 100
endif

goto down_held

' ============================================================
' FINE UP
' One PICAXE servo count
' ============================================================

fine_up:
if servoPosition < SERVO_MAX then

servoPosition = servoPosition + 1
servopos servoPin, servoPosition
endif

return

' ============================================================
' FINE DOWN
' One PICAXE servo count
' ============================================================

fine_down:
if servoPosition > SERVO_MIN then
servoPosition = servoPosition - 1
servopos servoPin, servoPosition
endif

return

' ============================================================
' COARSE UP
' Five PICAXE servo counts
' ============================================================

coarse_up:
if servoPosition < SERVO_MAX then

if servoPosition > COARSE_UP_LIMIT then
servoPosition = SERVO_MAX
else
servoPosition = servoPosition + COARSE_STEP
endif

servopos servoPin, servoPosition
endif

return

' ============================================================
' COARSE DOWN
' Five PICAXE servo counts
' ============================================================

coarse_down:
if servoPosition > SERVO_MIN then

if servoPosition < COARSE_DOWN_LIMIT then
servoPosition = SERVO_MIN
else
servoPosition = servoPosition - COARSE_STEP
endif

servopos servoPin, servoPosition
endif

return


Diagrams

 

Conditioning Board and Cal Box


 

 

Conditioning sub board

 

Picaxe with Conditioning and Cal

 

 

 

 

No comments: