Post Go back to editing

Detecting Rising or Falling Edges in .rule Conditions for State Machines in LTspice

Category: Software
Software Version: 24.0.12

Hello everyone,

I am working on a project in LTspice where I am using the .machine directive to create a state machine. My goal is to detect the rising (leading) or falling edge of a signal within the .rule conditions to trigger state transitions.

For example, I want to have a rule like this:

.machine
.state X
.state Y
.rule X Y {edge detection condition}
.endmachine

Where {edge detection condition} would allow me to detect a rising or falling edge of a certain signal (e.g., V(SAMPLE)).

I understand how to use basic voltage comparisons for state transitions, but I am not sure how to implement edge detection directly within the .rule conditions. Is there a way to detect edges in LTspice using the .rule command, or is there a workaround that could be used to achieve this functionality?

Any advice or examples from your experience would be greatly appreciated!

Thanks in advance!

Parents
  • I solved the problem as follows:

    1. Added a B source (voltage-controlled voltage source): I set the function to take the time derivative of the clock signal using the equation V=ddt(V(clock)). This allows me to track both the rising (leading) and falling edges of the clock signal.

    2. Implemented edge detection in the rules: Initially, I encountered an issue where the state would change multiple times during the rising edge. To resolve this, I introduced dummy states that wait for the falling edge of the clock signal. These dummy states ensure that the output state only changes on the rising edge, preventing multiple transitions during a single clock period.

    The solution for my project is a simple circuit representing a basic intersection with two traffic lights.
    .machine
     
        .state S0 0
        .state Stran1 1
        .state S1 2
        .state Stran2 3
        .state S2 4
        .state Stran3 5
        .state S3 6
        .state Stran4 7
     
        .rule S0 Stran1 ((V(edges) < 0))
        .rule Stran1 S1 ((V(edges) > 0) & (V(t) > .5))
        .rule S1 Stran2 ((V(edges) < 0))
        .rule Stran2 S2 ((V(edges) > 0) & (V(t) < .5))
        .rule S2 Stran3 ((V(edges) < 0))
        .rule Stran3 S3 ((V(edges) > 0) & (V(t) < .5))
        .rule S3 Stran4 ((V(edges) < 0))
        .rule Stran4 S0 ((V(edges) > 0) & (V(t) < .5))
        .rule * S0 V(reset) > .5
     
     
        .output states state
        .output G-SJ  state==0 | state==1
        .output R-VZ  state==0 | state==1
     
        .output Y-SJ state==2 | state==3
        .output R-VZ state==2 | state==3
     
        .output R-SJ state==4 | state==5
        .output G-VZ state==4 | state==5
     
        .output R-SJ state==6 | state==7
        .output Y-VZ state==6 | state==7
     
    .endmachine
Reply
  • I solved the problem as follows:

    1. Added a B source (voltage-controlled voltage source): I set the function to take the time derivative of the clock signal using the equation V=ddt(V(clock)). This allows me to track both the rising (leading) and falling edges of the clock signal.

    2. Implemented edge detection in the rules: Initially, I encountered an issue where the state would change multiple times during the rising edge. To resolve this, I introduced dummy states that wait for the falling edge of the clock signal. These dummy states ensure that the output state only changes on the rising edge, preventing multiple transitions during a single clock period.

    The solution for my project is a simple circuit representing a basic intersection with two traffic lights.
    .machine
     
        .state S0 0
        .state Stran1 1
        .state S1 2
        .state Stran2 3
        .state S2 4
        .state Stran3 5
        .state S3 6
        .state Stran4 7
     
        .rule S0 Stran1 ((V(edges) < 0))
        .rule Stran1 S1 ((V(edges) > 0) & (V(t) > .5))
        .rule S1 Stran2 ((V(edges) < 0))
        .rule Stran2 S2 ((V(edges) > 0) & (V(t) < .5))
        .rule S2 Stran3 ((V(edges) < 0))
        .rule Stran3 S3 ((V(edges) > 0) & (V(t) < .5))
        .rule S3 Stran4 ((V(edges) < 0))
        .rule Stran4 S0 ((V(edges) > 0) & (V(t) < .5))
        .rule * S0 V(reset) > .5
     
     
        .output states state
        .output G-SJ  state==0 | state==1
        .output R-VZ  state==0 | state==1
     
        .output Y-SJ state==2 | state==3
        .output R-VZ state==2 | state==3
     
        .output R-SJ state==4 | state==5
        .output G-VZ state==4 | state==5
     
        .output R-SJ state==6 | state==7
        .output Y-VZ state==6 | state==7
     
    .endmachine
Children
  • I was tinkering with the .machine statement for the first time recently and struggled with the same thing. Ultimately I also implemented a "dummy state" solution. Each "real" state has a corresponding "dummy" state which precedes it. To transition from the dummy state to its corresponding real state, all conditions which could cause transitions from the real state must be false. This prevents multiple transitions from single events.

    It feels like there should be a much easier way to do this though.I presume most state machines will be edge-sensitive, not level-sensitive.

    I thought the "tripdt" parameter would be useful for preventing extra transitions, but so far I have yet to observe it having any effect on behavior. Maybe I'm misunderstanding its purpose. It's only mentioned offhand in the documentation, without any examples.

  • Hi  & ,

    We'll look into this feature. Thanks.

    mike