Help debugging states with dc-motors

I’ve created a project similar to the traffic light example but I’ve been using a dc motor shield instead of the LEDs. I’m having an issue with the states connecting sequentially as it seems to be skipping or ignoring some of the states that I have included in the main function. I made a short video showing my problem and the code behind it. Please help me try to find out why my program is skipping states.

Here’s the link to the video:

Hello!

You’ve run into a shared resource problem. I haven’t published an article on dealing with it.

The main difference between your setup and the traffic light is actuator sharing between states. In the traffic light, no two states fight to control the same LED. In your case, both states try to control motors at the same time. One wants 0, another wants 1. Who wins is generally not predictable. That’s we the chassis looks like intractable.

There are two possible strategies to resolve the conflict:

  1. Use a single dc-motors node for the whole project. Make nodes to produce values for it, then on the main patch, in a single point decide which is “active” and send it to dc-motors.
  2. Keep the architecture the same, but add few xod/core/gate-number right before dc-motors instances to guard the driver against values conflict. Make sure no more than one gate is opened at any time point. Use flip-flop’s to keep the gate of the current state open.

Feel free to ask if you need clarification.

Thanks for the quick response. I can add the gates and flip-flops to make it work. I would like some clarification on why both states would be controlling the motors at the same time. My understanding from looking at the main function is that the “forward” patch gets called and is no longer active after the “done” pulse which initiates the “left” patch.

I suppose my question is why are they both running simultaneously when the flow of the program appears like they would be happening one after the other?

All depends on the execution model. Whether a system is reactive, functional, or a mix of two.

For the sake of simplicity, XOD values are functional. That means any particular output and any particular link has a value at any point in time. Think of nodes’ outputs as low-impedance IC pins, inputs as high-impedance IC pins, and links as wires. A wire (while connected) always has a voltage value on it, although it may be 0 (i.e. pulled down to GND). The same is here. When you duplicate dc-motors and effectively put multiple links onto a single input pin you get the same result if you’d connect a DC motor to two different motor shields at once. Each tries to win, but in the real world, one shield would burn, in XOD you get a racing behavior instead.

The only reactive type XOD has is Pulse.

To deal the shared resource problem we consider a language improvement that will introduce “Control inputs and outputs”. When a node is given control it awakes and initializes itself. When such node gives up the control it deinitializes itself and goes sleep. That could make implementing state-machines much more simple and expressive. However, it’s a complex feature with many edge-cases, I can’t say when we’ll implement it.

I’ve tried this with both the methods you suggested but I’m still not quite there. For the first method having the DC-Motor node in main I am not sure how to send numbers from different states to the same DC-Motor node since the motors can only have inputs from one value. I was thinking I could do this with the “any” node but I’m not sure how that would work with numbers instead of pulses. I’ve attached a screenshot of my main function (on the left) as well as my forward and reverse patch (on the right).

I also tried this using the second method you suggested by putting gates in front of the dc-motor node and controlling that with a flip-flop. When I uploaded the code to the Arduino it would run the motors forever and still never moved on to the next state.gateDCMotors

To demultiplex multiple inputs in the first example you could use the select node. Two of them in your case right before dc-motors

In the second example, I miss a screenshot of the third patch. Is there something that should stop motors so that they are not run forever? I mean does another state is constructed the same way? What values are bound to gate-number in both cases?

For the second example the forward and reverse patches are both the same structure but the value bound to gate-number is 1 for forward and -1 for reverse.

My thought was at the end of the delay the flip flop would close the gate and no longer send values to the motor. I’m not sure why this is not the case.

How can I modify this to make it where values are not being sent to the motor unless that specific patch is set as the current state?

Yes, it should work so. Can you provide a xodball (File → Export Project)? I will take a look.

Here’s the project.motorWithGates.xodball (11.1 KB)

Oh. Here is the fix:

Screenshot from 2017-12-19 17-19-54

Note the added defer-pulse node.

Now why it works this way and doesn’t without deferring. What happens when the delay is done. It fires updates on two branches: the left one sends a start signal to the next state and the right one closes the gate. At the same time the next state opens the gate. Simultaneously the gates are opening and closing, the state is not stable, the first gate wins, you see no change.

Adding the defer-pulse postpones the next state activation for a smallest possible delay. And all start work fine.

Yeah, I know, it’s mind-blowing and complicated :exploding_head: I’m thinking about a simpler workaround pattern for working with a shared resource until we would implement the control inputs/outputs.

Some good news. I did get it to work with the single DC-Motor node in the main function and the “select” node. The right picture shows my forward, reverse, and stop functions with the only difference being the numbers bound to the gate. It works fine but it seems messy and not the best flow of the program, especially if I want to add more patches for turnLeft, stop, etc… I guess I’d have to daisy chain a bunch of select nodes together or create my own custom select node with more than two inputs. In the picture I’ve got another “stop” node that I’d like to implement but haven’t quite got there yet. But, the good news is it does work and runs just as expected!

The other version is the structure I would much prefer to use and would make for a better program. I tried adding the “defer-pulse” node but I’m still getting mixed results. It seems that it is working better but still not the way I would expect. For example the picture shows my main function on the left and the structure of the forward, reverse, and stop nodes on the right with the only difference being the number bound to the gates. When I upload this program to the Arduino the reverse state gets skipped but the forward and stop act as expected. Still there are other instances of odd behavior with states getting skipped or running forever depending on how I structure the main function.

Yep. That’s an academically “true way” that leads to absolutely impractical reality. I wonder if we can make some little improvement or a new pattern to resolve the mess. Have no ideas for the moment, unfortunately.

Yeah, select-N can be built with select-(N-1) and if-else. My non-tech colleague actually did that :grin:

That’s quite surprising. Should work. Would you attach the updated *.xodball? Maybe I’ll find a problem.

Here’s the project. Thanks for taking a look.motorWithGatesAddDefer.xodball (12.6 KB)

Pardon for the delay.

Uff… it looked like you did everything right. But trying to understand what’s going on I found yet more problems with shared resource state management.

First, you have to delay the boot itself because all states initially try to send their initial value to dc-motors which cause a race condition. Postponing the boot starts the first state when things already settle down and the gates in other states have been closed.

Next, there was a problem in dc-motors C++ implementation:

    if (dirByte != state->lastDirByte) {
        digitalWrite(DIR_LATCH, LOW);
        shiftOut(DIR_SER, DIR_CLK, MSBFIRST, dirByte);
        digitalWrite(DIR_LATCH, HIGH);
        state->lastDirByte = dirByte;
    }

Although this is correct if there’s only one dc-motors node it works not as we expect when multiple instances manage the same motor. A node could “think” that motor direction is correct because it already set it up, but don’t know whether another instance has changed it or not.

I’ve updated the library to v1.0.1. Install nkrkv/af-motor again to get the fix.

Sadly to admit, but the pattern of state management which we suggest is not intuitive nor usable at scale. I’ll try to find a better way. Meanwhile, the hacks will help to go on with the robot, that’s all I can offer at the moment.

YES!! Thanks for your help! Here’s a real rough video of the robot moving around. I’ll end up with a more polished video that I’ll share soon. https://www.youtube.com/watch?v=X6ZDi9gYQkg&feature=youtu.be

2 Likes

Excellent! :heart: Thrilled to see more :blush: