diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 1905f359..32605fff 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -16,6 +16,9 @@
     - Make ExpressionScalar hashable
     - Fix bug that prevented evaluation of expressions containing some special functions (`erfc`, `factorial`, etc.)
 
+- Parameters:
+    - `ConstantParameter` now accepts a `Expression` without free variables as value (given as `Expression` or string)
+
 ## 0.2 ##
 
 - General:
diff --git a/qupulse/pulses/parameters.py b/qupulse/pulses/parameters.py
index 13b2478c..f4fbbc94 100644
--- a/qupulse/pulses/parameters.py
+++ b/qupulse/pulses/parameters.py
@@ -16,7 +16,7 @@ import sympy
 import numpy
 
 from qupulse.serialization import AnonymousSerializable
-from qupulse.expressions import Expression
+from qupulse.expressions import Expression, ExpressionVariableMissingException
 from qupulse.utils.types import HashableNumpyArray, DocStringABCMeta
 
 __all__ = ["Parameter", "ConstantParameter",
@@ -49,7 +49,7 @@ class Parameter(metaclass=DocStringABCMeta):
 
     @abstractmethod
     def __hash__(self) -> int:
-        pass
+        """Returns a hash value of the parameter. Must be implemented."""
 
     def __eq__(self, other) -> bool:
         return type(self) is type(other) and hash(self) == hash(other)
@@ -58,17 +58,22 @@ class Parameter(metaclass=DocStringABCMeta):
 class ConstantParameter(Parameter):
     """A pulse parameter with a constant value."""
     
-    def __init__(self, value: Union[Real, numpy.ndarray]) -> None:
+    def __init__(self, value: Union[Real, numpy.ndarray, Expression, str, sympy.Expr]) -> None:
         """Create a ConstantParameter instance.
 
         Args:
             value (Real): The value of the parameter
         """
         super().__init__()
-        if isinstance(value, Real):
-            self._value = value
-        else:
-            self._value = numpy.array(value).view(HashableNumpyArray)
+        try:
+            if isinstance(value, Real):
+                self._value = value
+            elif isinstance(value, (str, Expression, sympy.Expr)):
+                self._value = Expression(value).evaluate_numeric()
+            else:
+                self._value = numpy.array(value).view(HashableNumpyArray)
+        except ExpressionVariableMissingException:
+            raise RuntimeError("Expressions passed into ConstantParameter may not have free variables.")
         
     def get_value(self) -> Union[Real, numpy.ndarray]:
         return self._value

Allow ConstantParameter to accept variable-free sympy expressions.
currently only accepts Real number types or ndarrays
diff --git a/tests/pulses/bug_tests.py b/tests/pulses/bug_tests.py
index d632f844..3f66482e 100644
--- a/tests/pulses/bug_tests.py
+++ b/tests/pulses/bug_tests.py
@@ -49,9 +49,7 @@ class BugTests(unittest.TestCase):
 
         _ = plot(sequence_template, parameters=sequence_parameters, sample_rate=100, show=False)
 
-    @unittest.expectedFailure
     def test_plot_with_parameter_value_being_expression_string(self) -> None:
-        """This is currently not supported but probably should be?"""
         sine_measurements = [('M', 't_duration/2', 't_duration')]
         sine = FunctionPulseTemplate('a*sin(omega*t)', 't_duration', measurements=sine_measurements)
         sine_channel_mapping = dict(default='sin_channel')
diff --git a/tests/pulses/parameters_tests.py b/tests/pulses/parameters_tests.py
index 3e995604..ac3b78cb 100644
--- a/tests/pulses/parameters_tests.py
+++ b/tests/pulses/parameters_tests.py
@@ -25,6 +25,26 @@ class ConstantParameterTest(unittest.TestCase):
         constant_parameter = ConstantParameter(0.2)
         self.assertEqual("<ConstantParameter 0.2>", repr(constant_parameter))
 
+    def test_expression_value(self) -> None:
+        expression_str = "exp(4)*sin(pi/2)"
+        expression_obj = Expression(expression_str)
+        expression_val = expression_obj.evaluate_numeric()
+        param = ConstantParameter(expression_str)
+        self.assertEqual(expression_val, param.get_value())
+        param = ConstantParameter(expression_obj)
+        self.assertEqual(expression_val, param.get_value())
+
+    def test_invalid_expression_value(self) -> None:
+        expression_obj = Expression("sin(pi/2*t)")
+        with self.assertRaises(RuntimeError):
+            ConstantParameter(expression_obj)
+
+    def test_numpy_value(self) -> None:
+        import numpy as np
+        arr = np.array([6, 7, 8])
+        param = ConstantParameter(arr)
+        np.array_equal(arr, param.get_value())
+
 
 class MappedParameterTest(unittest.TestCase):
 
@@ -87,10 +107,12 @@ class ParameterConstraintTest(unittest.TestCase):
             ParameterConstraint('a*b')
         ParameterConstraint('1 < 2')
 
-    def test_str(self):
+    def test_str_and_serialization(self):
         self.assertEqual(str(ParameterConstraint('a < b')), 'a < b')
+        self.assertEqual(ParameterConstraint('a < b').get_serialization_data(), 'a < b')
 
         self.assertEqual(str(ParameterConstraint('a==b')), 'a==b')
+        self.assertEqual(ParameterConstraint('a==b').get_serialization_data(), 'a==b')
 
 
 class ParameterNotProvidedExceptionTests(unittest.TestCase):
diff --git a/tests/pulses/pulse_template_tests.py b/tests/pulses/pulse_template_tests.py
index 6fe7a7dc..73d66223 100644
--- a/tests/pulses/pulse_template_tests.py
+++ b/tests/pulses/pulse_template_tests.py
@@ -164,12 +164,12 @@ class PulseTemplateTest(unittest.TestCase):
 
     def test_create_program(self) -> None:
         template = PulseTemplateStub(defined_channels={'A'}, parameter_names={'foo'})
-        parameters = {'foo': ConstantParameter(2.126), 'bar': -26.2, 'hugo': '2*x+b', 'append_a_child': '1'}
+        parameters = {'foo': ConstantParameter(2.126), 'bar': -26.2, 'hugo': 'exp(sin(pi/2))', 'append_a_child': '1'}
         measurement_mapping = {'M': 'N'}
         channel_mapping = {'A': 'B'}
 
         expected_parameters = {'foo': ConstantParameter(2.126), 'bar': ConstantParameter(-26.2),
-                               'hugo': ConstantParameter('2*x+b'), 'append_a_child': ConstantParameter('1')}
+                               'hugo': ConstantParameter('exp(sin(pi/2))'), 'append_a_child': ConstantParameter('1')}
         to_single_waveform = {'voll', 'toggo'}
         global_transformation = TransformationStub()
 
@@ -308,11 +308,11 @@ class PulseTemplateTest(unittest.TestCase):
 
     def test_create_program_none(self) -> None:
         template = PulseTemplateStub(defined_channels={'A'}, parameter_names={'foo'})
-        parameters = {'foo': ConstantParameter(2.126), 'bar': -26.2, 'hugo': '2*x+b'}
+        parameters = {'foo': ConstantParameter(2.126), 'bar': -26.2, 'hugo': 'exp(sin(pi/2))'}
         measurement_mapping = {'M': 'N'}
         channel_mapping = {'A': 'B'}
         expected_parameters = {'foo': ConstantParameter(2.126), 'bar': ConstantParameter(-26.2),
-                               'hugo': ConstantParameter('2*x+b')}
+                               'hugo': ConstantParameter('exp(sin(pi/2))')}
         expected_internal_kwargs = dict(parameters=expected_parameters,
                                         measurement_mapping=measurement_mapping,
                                         channel_mapping=channel_mapping,

pip3 install .[plotting,zurich-instruments,tektronix,Faster-fractions]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
apt-get update apt-get install -y libgmp-dev libmpfr-dev libmpc-dev
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
cached-property==1.5.2
certifi==2021.5.30
coverage==6.2
cycler==0.11.0
execnet==1.9.0
gmpy2==2.1.5
importlib-metadata==4.8.3
iniconfig==1.1.1
kiwisolver==1.3.1
matplotlib==3.3.4
mpmath==1.3.0
numpy==1.19.5
packaging==21.3
Pillow==8.4.0
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
pytest-asyncio==0.16.0
pytest-cov==4.0.0
pytest-mock==3.6.1
pytest-xdist==3.0.2
python-dateutil==2.9.0.post0
qupulse @ file:///qupulse
six==1.17.0
sympy==1.9
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: qupulse
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
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_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
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - 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
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - cached-property==1.5.2
      - coverage==6.2
      - cycler==0.11.0
      - execnet==1.9.0
      - gmpy2==2.1.5
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - kiwisolver==1.3.1
      - matplotlib==3.3.4
      - mpmath==1.3.0
      - numpy==1.19.5
      - packaging==21.3
      - pillow==8.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-asyncio==0.16.0
      - pytest-cov==4.0.0
      - pytest-mock==3.6.1
      - pytest-xdist==3.0.2
      - python-dateutil==2.9.0.post0
      - qupulse==0.2
      - six==1.17.0
      - sympy==1.9
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/qupulse

tests/pulses/bug_tests.py::BugTests::test_plot_with_parameter_value_being_expression_string tests/pulses/parameters_tests.py::ConstantParameterTest::test_expression_value tests/pulses/parameters_tests.py::ConstantParameterTest::test_invalid_expression_value
tests/pulses/bug_tests.py::BugTests::test_plotting_two_channel_function_pulse_after_two_channel_table_pulse_crash tests/pulses/parameters_tests.py::ParameterConstraintTest::test_equal tests/pulses/parameters_tests.py::ParameterConstraintTest::test_expressions tests/pulses/parameters_tests.py::ParameterConstraintTest::test_no_relation tests/pulses/parameters_tests.py::ParameterConstraintTest::test_ordering tests/pulses/parameters_tests.py::ParameterConstraintTest::test_str_and_serialization
tests/pulses/parameters_tests.py::ConstantParameterTest::test_float_values tests/pulses/parameters_tests.py::ConstantParameterTest::test_numpy_value tests/pulses/parameters_tests.py::ConstantParameterTest::test_repr tests/pulses/parameters_tests.py::ConstantParameterTest::test_requires_stop tests/pulses/parameters_tests.py::MappedParameterTest::test_repr tests/pulses/parameters_tests.py::MappedParameterTest::test_requires_stop_and_get_value tests/pulses/parameters_tests.py::ParameterNotProvidedExceptionTests::test tests/pulses/parameters_tests.py::InvalidParameterNameExceptionTests::test tests/pulses/pulse_template_tests.py::PulseTemplateTest::test__create_program tests/pulses/pulse_template_tests.py::PulseTemplateTest::test__create_program_single_waveform tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_create_program tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_create_program_channel_mapping tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_create_program_defaults tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_create_program_none tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_matmul tests/pulses/pulse_template_tests.py::PulseTemplateTest::test_rmatmul tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_build_sequence tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_build_sequence_no_waveform tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_internal_create_program tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_internal_create_program_missing_parameters tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_internal_create_program_no_waveform tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_internal_create_program_transformation tests/pulses/pulse_template_tests.py::AtomicPulseTemplateTests::test_is_interruptable
ReleaseNotes.txt qupulse/pulses/parameters.py
ReleaseNotes.txt qupulse/pulses/parameters.py