Sequence of Bones rotate One by One - Controlled by One Bone
Use self in drivers.

Similarly to @joshsanfelici have set the bones to XYZ Euler and driven the rotation z property of each bone via the target bone.
The ability to use self in drivers let's us get away with having one common driver and feed into it object properties.
In this case if one of our pose bones is self and the target bone is named &quot;Bone&quot; and is in the same armature then
self.id_data.pose.bones[&quot;Bone&quot;]

is the target bone, and
self.id_data.pose.bones[&quot;Bone&quot;].rotation_euler.z

is its $Z$ axis Euler rotation.
If we add a custom property to each bone, eg &quot;prop&quot; it can be used as the start rotation, eg
self[&quot;prop&quot;] = 0.0

Rotations are in Eulers, as explained in other answer. So for example sake, if &quot;prop2&quot; is $\pi / 2$ can drive the bone using the target bone using a pretty long an inelegant expression that is the maximum of the minimum between 0 and the target rotation subtract the start range, and the range between our props...
Instead I have written a little script to add some props, make a simple UI, and a driver expression.  The UI is appended to the Pose Mode options panel in the 3D view N Tools Panel.
import bpy
from bpy.props import FloatVectorProperty, StringProperty
from math import radians

## properties

bpy.types.PoseBone.copy_range = FloatVectorProperty(
        size=2,
        unit='ROTATION',
        default=(0.0,radians(90)),
        )

bpy.types.PoseBone.target = StringProperty(
        )

# UI 

def draw(self, context):
    ob = context.object
    pb = context.active_pose_bone
    self.layout.label(text=&quot;Bone Switch Test&quot;)
    self.layout.prop(pb, &quot;rotation_euler&quot;, index=2)
    self.layout.prop(pb, &quot;copy_range&quot;)
    self.layout.prop_search(pb, &quot;target&quot;, ob.pose, &quot;bones&quot;)
    

bpy.types.VIEW3D_PT_tools_posemode_options.append(draw)


## driver expression

def rotate_switch(self):
    target = self.id_data.pose.bones.get(self.target)
    if target:
        rz = self.copy_range
        range = rz[1] - rz[0]
        # map to 0 : range
        trz = target.rotation_euler.z
        return min(max(0, trz - rz[0]), range)  

    return 0.0
    
bpy.app.driver_namespace[&quot;rotate_switch&quot;] = rotate_switch

See the driver expression is
min(max(0, trz - rz[0]), range)

where trz is the target $Z$ rotation, rz[0] is at which rotation of target our bone starts, and range is the end minus the start of our bones rotation.
Easily extendable.
The idea here is to make it as easy to extend as possible. Can copy any of the driven bones and change their rotation range and the name of the driving bone on the fly.
Can edit the driver function and re-run the script, for example this simple change, (dividing the target rot by 4)
    trz = target.rotation_euler.z / 4

to make the &quot;hammers&quot; fall 90 degrees for each revolution of target bone.

Also here is a little helper script to convert all selected pose bones to XYZ euler rotation, and add a driver to all selected bar the active. (assumed the active is the driving bone)
import bpy

context = bpy.context


for pb in context.selected_pose_bones:
    pb.rotation_mode = 'XYZ'
    if pb is context.active_pose_bone:
        continue
    fcurve = pb.driver_add(&quot;rotation_euler&quot;, 2)
    driver = fcurve.driver
    driver.use_self = True
    driver.expression = &quot;rotate_switch(self)&quot;