diff --git a/mpf/config_players/coil_player.py b/mpf/config_players/coil_player.py
index 9fe7fc5d1..ee67b8552 100644
--- a/mpf/config_players/coil_player.py
+++ b/mpf/config_players/coil_player.py
@@ -27,16 +27,22 @@ class CoilPlayer(DeviceConfigPlayer):
             if not isinstance(coil, Driver):
                 self.raise_config_error("Invalid coil name {}".format(coil), 2, context=context)
             action = s.pop('action')
-            coil_action = getattr(coil, action, None)
-            if not coil_action:
-                self.raise_config_error("Invalid action {}".format(action), 1, context=context)
 
-            if action in ("disable", "off") and coil.name in instance_dict:
+            # delete coil from dict
+            try:
                 del instance_dict[coil.name]
+            except KeyError:
+                pass
+
+            if action in ("disable", "off"):
+                coil.disable(**s)
             elif action in ("on", "enable"):
                 instance_dict[coil.name] = coil
-
-            coil_action(**s)
+                coil.enable(**s)
+            elif action == "pulse":
+                coil.pulse(**s)
+            else:
+                self.raise_config_error("Invalid action {}".format(action), 1, context=context)
 
     def clear_context(self, context):
         """Disable enabled coils."""
diff --git a/mpf/config_spec.yaml b/mpf/config_spec.yaml
index da85e2565..afe7a653e 100644
--- a/mpf/config_spec.yaml
+++ b/mpf/config_spec.yaml
@@ -266,7 +266,7 @@ fast_coils:
     recycle_ms: single|ms|None
 coil_player:
     __valid_in__: machine, mode, show
-    action: single|lstr|pulse
+    action: single|enum(pulse,on,off,enable,disable)|pulse
     hold_power: single|float|None
     pulse_power: single|float|None
     pulse_ms: single|int|None

coil_player action 'off' crashes out
Using 'off' as an action in a coil_player generates (at run time) an error that the action is not valid (**_Invalid action off_**).  Easily worked-around by using 'disabled' instead, but either the code needs fixing or the documentation updating.

So this works fine when the ball_cleared_ramp event comes in..

```
# Will activate a divertor depending on which lock is our target.  
coil_player:
   route_to_lock1:
      c_lowerDivertor:
         action: pulse
         pulse_ms: 3000
   route_to_lock2:
      c_upperDivertor:
         action: pulse
         pulse_ms: 3000
   ball_cleared_ramp: # Divertor did it's job, so can be switched off
      c_upperDivertor:
         action: disable
      c_lowerDivertor:
         action: disable
```

However with this config instead..

```
# Will activate a divertor depending on which lock is our target. 
coil_player:
   route_to_lock1:
      c_lowerDivertor:
         action: pulse
         pulse_ms: 3000
   route_to_lock2:
      c_upperDivertor:
         action: pulse
         pulse_ms: 3000
   ball_cleared_ramp: # Divertor did it's job, so can be switched off
      c_upperDivertor:
         action: off
      c_lowerDivertor:
         action: off
```

This is the error from the log..

Traceback (most recent call last):
  File "c:\users\mark\appdata\local\programs\python\python36\lib\site-packages\mpf\core\events.py", line 657, in _run_handlers
    result = handler.callback(**merged_kwargs)
  File "c:\users\mark\appdata\local\programs\python\python36\lib\site-packages\mpf\core\config_player.py", line 336, in config_play_callback
    **kwargs)
  File "c:\users\mark\appdata\local\programs\python\python36\lib\site-packages\mpf\config_players\coil_player.py", line 32, in play
    self.raise_config_error("Invalid action {}".format(action), 1, context=context)
  File "c:\users\mark\appdata\local\programs\python\python36\lib\site-packages\mpf\core\logging.py", line 139, in raise_config_error
    raise ConfigFileError(msg, error_no, self.log.name, context)
mpf.exceptions.ConfigFileError.ConfigFileError: Config File Error in coil_player: Invalid action off Error Code: CFE-coil_player-1 Context: lock_handler



diff --git a/mpf/tests/machine_files/coil_player/config/coil_player.yaml b/mpf/tests/machine_files/coil_player/config/coil_player.yaml
index 0e0cbf253..b749a1335 100644
--- a/mpf/tests/machine_files/coil_player/config/coil_player.yaml
+++ b/mpf/tests/machine_files/coil_player/config/coil_player.yaml
@@ -41,6 +41,12 @@ coil_player:
     coil_3: disable
   event9:
     coil_3: 30
+  event10:
+    coil_1:
+      action: on
+  event11:
+    coil_1:
+      action: off
   pulse_1_100:
     coil_1:
       action: pulse
@@ -49,4 +55,4 @@ coil_player:
     coil_1:
       action: pulse
       pulse_ms: 50
-      max_wait_ms: 100
\ No newline at end of file
+      max_wait_ms: 100
diff --git a/mpf/tests/test_CoilPlayer.py b/mpf/tests/test_CoilPlayer.py
index a079f556d..d5f2c4707 100644
--- a/mpf/tests/test_CoilPlayer.py
+++ b/mpf/tests/test_CoilPlayer.py
@@ -127,6 +127,22 @@ class TestCoilPlayer(MpfTestCase):
 
         coil.hw_driver.disable.assert_called_with()
 
+        # same again but use on and off instead of enable and disable
+        coil.hw_driver.enable = MagicMock()
+        coil.hw_driver.pulse = MagicMock()
+        coil.hw_driver.disable = MagicMock()
+
+        self.machine.events.post('event10')
+        self.advance_time_and_run()
+
+        coil.hw_driver.enable.assert_called_with(PulseSettings(power=1.0, duration=10), HoldSettings(power=1.0))
+        assert not coil.hw_driver.pulse.called
+
+        self.machine.events.post('event11')
+        self.advance_time_and_run()
+
+        coil.hw_driver.disable.assert_called_with()
+
     def test_coil_player_in_mode(self):
         coil = self.machine.coils['coil_3']
         coil.hw_driver.enable = MagicMock()
@@ -158,4 +174,4 @@ class TestCoilPlayer(MpfTestCase):
         self.assertEqual("pulsed_100", coil.hw_driver.state)
         # after pulse end
         self.advance_time_and_run(.06)
-        self.assertEqual("pulsed_50", coil.hw_driver.state)
\ No newline at end of file
+        self.assertEqual("pulsed_50", coil.hw_driver.state)

pip install -e .
parse_log_pytest
pytest
pytest
apt-get update apt-get install -y gcc
3.6
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
asciimatics==1.14.0
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
future==1.0.0
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
-e git+https://github.com/missionpinball/mpf.git@e67b40d891febb679279708351a6fb2560889b9f#egg=mpf
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
Pillow==8.4.0
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
psutil==7.0.0
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyfiglet==0.8.post1
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pyserial==3.5
pyserial-asyncio==0.6
pytest==6.2.4
ruamel.base==1.0.0
ruamel.yaml==0.10.23
terminaltables==3.1.10
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing==3.7.4.3
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
wcwidth==0.2.13
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: mpf
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - asciimatics==1.14.0
      - future==1.0.0
      - pillow==8.4.0
      - psutil==7.0.0
      - pyfiglet==0.8.post1
      - pyserial==3.5
      - pyserial-asyncio==0.6
      - ruamel-base==1.0.0
      - ruamel-yaml==0.10.23
      - terminaltables==3.1.10
      - typing==3.7.4.3
      - wcwidth==0.2.13
prefix: /opt/conda/envs/mpf

mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_enable_and_disable
mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_coil_player_in_mode mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_express_config mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_max_wait_ms mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_pulse mpf/tests/test_CoilPlayer.py::TestCoilPlayer::test_pulse_with_attributes
mpf/config_spec.yaml mpf/config_players/coil_player.py
mpf/config_spec.yaml mpf/config_players/coil_player.py