Simple light barrier – Part 1

For a project I’m currently working on I need a light barrier. For maximum efficiency the light barrier should have a high resistance in idle state and in triggered state it should have a low resistance, because it will be most time in idle state. There were some building kits for light barriers in my favourite electronic shop, but they need too much space for my project so I need something more compact. Another point is that they use relays for switching which are too sluggish for my application, need too much electrical power and are too expensive for me because I need many of them. So I decided to design it own my own:

Lichtschranke (bei Dunkelheit leitend)

In Idle state, the light, emitted by the LED is being catched by the photo diode (can also be a photo transistor if necessary), so a high current flows through the photo diode and the resistor Rn. This results in a positive gate-source voltage of the p-chanel MOSFET, so it locks the current flow through the consumer Rv. For reducing enegy loss, the resistance Rn should be as high as possible. In triggered state, nearly no current flows through the photo diode, so the gate-source voltage of the MOSFET is negative, so the MOSFET will turn on and let the current flow through the consumer Rv. The resistance Rb is just a base resistance for protecting the LED from overvoltage.

I will build a prototype of this circuit at the end of this month and will post my test results on this blog.

Simple light barrier – Part 2

How to use mocks

At this weekend I decided to refactor some parts of the circuit simulator, because its source slowly becomes confusing. In detail I began to extract the graph package of the simulator into a new module which can also be used in other projects relying on a graph library. While I was doing this I found out how I can use Mockito for improving my unit tests.

Mockito is a framework for mock creation. This means it wraps classes which your unit tests depend on into dummy classes returning some hardcoded values.

The advantage of this is, that you don’t need working implementations of interfaces which are dependencies of your unit tests but not being part of the functionality you want to test.

Here is an example of an unit test using mocks:

class DijkstraAlgorithmTest {
    private Graph<Integer> graph;
    private List<Node<Integer>> nodes;

    @BeforeEach
    void setUp() throws EdgeException {
        nodes = new LinkedList<>();
        for (int i = 0; i < 10; i++){
            Node<Integer> node = mock(Node.class);
            nodes.add(node);
            when(node.getData()).thenReturn(i);
            when(node.toString()).thenReturn(String.valueOf(i));
        }

        List<Edge<Integer>> edges = new ArrayList<>();
        Edge<Integer> edge;
        edge = mock(Edge.class); //0
        when(edge.getTarget(nodes.get(0))).thenReturn(nodes.get(1));
        when(edge.getTarget(nodes.get(1))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(0))).thenReturn(nodes.get(1));
        edges.add(edge);
        edge = mock(Edge.class); //1
        when(edge.getTarget(nodes.get(1))).thenReturn(nodes.get(4));
        when(edge.getTarget(nodes.get(4))).thenReturn(nodes.get(1));
        when(edge.getSource(nodes.get(4))).thenReturn(nodes.get(1));
        when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(4));
        edges.add(edge);
        edge = mock(Edge.class); //2
        when(edge.getTarget(nodes.get(4))).thenReturn(nodes.get(6));
        when(edge.getTarget(nodes.get(6))).thenReturn(nodes.get(4));
        when(edge.getSource(nodes.get(6))).thenReturn(nodes.get(4));
        when(edge.getSource(nodes.get(4))).thenReturn(nodes.get(6));
        edges.add(edge);
        edge = mock(Edge.class); //3
        when(edge.getTarget(nodes.get(0))).thenReturn(nodes.get(6));
        when(edge.getTarget(nodes.get(6))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(6))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(0))).thenReturn(nodes.get(6));
        edges.add(edge);
        edge = mock(Edge.class); //4
        when(edge.getTarget(nodes.get(6))).thenReturn(nodes.get(2));
        when(edge.getTarget(nodes.get(2))).thenReturn(nodes.get(6));
        when(edge.getSource(nodes.get(2))).thenReturn(nodes.get(6));
        when(edge.getSource(nodes.get(6))).thenReturn(nodes.get(2));
        edges.add(edge);
        edge = mock(Edge.class); //5
        when(edge.getTarget(nodes.get(2))).thenReturn(nodes.get(1));
        when(edge.getTarget(nodes.get(1))).thenReturn(nodes.get(2));
        when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(2));
        when(edge.getSource(nodes.get(2))).thenReturn(nodes.get(1));
        edges.add(edge);
        edge = mock(Edge.class); //6
        when(edge.getTarget(nodes.get(2))).thenReturn(nodes.get(3));
        when(edge.getTarget(nodes.get(3))).thenReturn(nodes.get(2));
        when(edge.getSource(nodes.get(3))).thenReturn(nodes.get(2));
        when(edge.getSource(nodes.get(2))).thenReturn(nodes.get(3));
        edges.add(edge);
        edge = mock(Edge.class); //7
        when(edge.getTarget(nodes.get(1))).thenReturn(nodes.get(3));
        when(edge.getTarget(nodes.get(3))).thenReturn(nodes.get(1));
        when(edge.getSource(nodes.get(3))).thenReturn(nodes.get(1));
        when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(3));
        edges.add(edge);

        graph = mock(Graph.class);
        when(graph.getAllNodes()).thenReturn(new HashSet<>(nodes));
        when(graph.getAllEdges()).thenReturn(new HashSet<>(edges));
        when(graph.getEdges(nodes.get(0))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(0),
                edges.get(3)
        )));
        when(graph.getEdges(nodes.get(1))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(0),
                edges.get(1),
                edges.get(5),
                edges.get(7)
        )));
        when(graph.getEdges(nodes.get(2))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(4),
                edges.get(5),
                edges.get(6)
        )));
        when(graph.getEdges(nodes.get(3))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(6),
                edges.get(7)
        )));
        when(graph.getEdges(nodes.get(4))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(1),
                edges.get(2)
        )));
        when(graph.getEdges(nodes.get(6))).thenReturn(new HashSet<>(Arrays.asList(
                edges.get(2),
                edges.get(3),
                edges.get(4)
        )));
    }

    @Test
    void apply1() {
        assertEquals(new Path<>(Arrays.asList(
                nodes.get(0),
                nodes.get(1),
                nodes.get(3)
        )), new DijkstraAlgorithm<Integer>().apply(graph, new DijkstraAlgorithm.Parameters<>(nodes.get(0), nodes.get(3))));
    }

    @Test
    void apply2() {
        assertEquals(new Path<>(Arrays.asList(
                nodes.get(4),
                nodes.get(1),
                nodes.get(3)
        )), new DijkstraAlgorithm<Integer>().apply(graph, new DijkstraAlgorithm.Parameters<>(nodes.get(4), nodes.get(3))));
    }
}

 

Let’s take a more detailed look into what happens in this piece of code. First a list of mocked objects of type Node is created. Node is an interface representing nodes in a graph.

nodes = new LinkedList<>();
        for (int i = 0; i < 10; i++){
            Node<Integer> node = mock(Node.class);
            nodes.add(node);
            when(node.getData()).thenReturn(i);
            when(node.toString()).thenReturn(String.valueOf(i));
        }

The mock(Node.class) instruction creates a new instance of an anonymous class implementing the interface Node.At this point, all methods of the created instance will return null. To be able to work with that instance, it is necessary to specify for each function the unit test will use what it should do.

This is done by the when(…).then(…) instructions:

when(node.getData()).thenReturn(i);

This specifies, that the value of the loop counter i shall be returned when the function getData() of the Node instance is called.

when(node.toString()).thenReturn(String.valueOf(i));

I included this for debugging purposes. It returns the loop counter i formatted into a String when the toString() method of the instance is called. The unit test itself does not use this function, but it make debugging easier because I better can see which node I have when looking at the variables stack of my IDE.

After this it is necessary to mock some edge instances for the graph to be tested:

List<Edge<Integer>> edges = new ArrayList<>();
        Edge<Integer> edge;
        edge = mock(Edge.class); //0
        when(edge.getTarget(nodes.get(0))).thenReturn(nodes.get(1));
        when(edge.getTarget(nodes.get(1))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(0));
        when(edge.getSource(nodes.get(0))).thenReturn(nodes.get(1));
        edges.add(edge);
        ...

Create a new mocked instance of an Edge by calling mock(Edge.class). Now specify the getTarget(…) and getSource(…) functions of the Edge:

when(edge.getTarget(nodes.get(0))).thenReturn(nodes.get(1));

This specifies that the node at position 1 of the list nodes shall be returned when getTarget(…) is called for the Edge with the node at position 0 of the list nodes.

when(edge.getSource(nodes.get(1))).thenReturn(nodes.get(0));

This specifies that the node at position 0 of the list nodes is being returned when calling getSource(…) for the Edge with the node at position 1 of the list nodes.

The same way the a mocked instance of Graph is created. Then the actual test is created:

@Test
    void apply1() {
        assertEquals(new Path<>(Arrays.asList(
                nodes.get(0),
                nodes.get(1),
                nodes.get(3)
        )), new DijkstraAlgorithm<Integer>().apply(graph, new DijkstraAlgorithm.Parameters<>(nodes.get(0), nodes.get(3))));
    }

As you can see, you now can use the mocked instances like normal implementations of Graph, Edge and Node.

Priorized Voltage Source Switch

I have been asked by a workmate if I could design a circuit which dynamically switches to another voltage source if the voltage of the primary source has dropped. He wants to install Solarpanels and would like to have a circuit which primarly uses the batteries being loaded by solar panels, for powering some lightening, but when the batteries are low, the power should be taken from the energy network. So I did some google research and some thinking and finally got the following circuit:

Schematics

The red bordered area represents the batteries (the capacitor on the left) and the solar panels (the 12 Volt voltage source on the right and the switch on the top, simulating the sun shining on the solar panels). The 12 Volt voltage source left next to the red bordered area represents the power from the energy network after it has been transformed down to 12 Volt and having passed a rectifier. When the batteries are loaded, the P-Channel MOSFET is turned off, so the power is taken from the batteries. The diode which is passed by the current from the batteries, prevents the current to flow from the energy net to the batteries, so the batteries only will be loaded by the solar panels.

The part on the left (consisting of the bipolar transistor, the base resistance, the TVS diode and the consumer resistance) is a simple voltage regulator circuit as it can be found on wikipedia. The TVS diode of the circuit limits the voltage of the consumer to a fixed value. So if you choose a TVS diode with a breakthrough voltage of 12 Volt, the consumer will get a maximum voltage of 12 Volt. The bipolar transistor regulates the current flow in a way that it will be constant for the consumer.

When the voltage of the batteries drop, the P-Channel MOSFET will turn on, so the reduce in voltage and current flow will be compensated by the energy network. The lower the battery get, the more power will be taken from the energy network. In my simulation, the voltage of the batteries dropped from 12 Volt to ~9 Volt, then no more power was taken from the batteries and all power flowed from the energy network.

The PathStar-Algorithm

For the circuit simulator I need a way to find parallel paths in a graph. To prepare the actual parallel path detection I first need to split a given path into a set of subpaths wich start and end at nodes spawning multiple branches. After some thinking I found out following algorithm:

public Set<Path<V>> apply(Graph<V> graph, PathStar.Parameters<V>... parameters) {
    assert graph != null;
    assert parameters != null;
    assert parameters.length > 0;

    PathStar.Parameters<V> params = parameters[0];
    Set<Path<V>> paths = new HashSet<>();

    List<Node<V>> subPath = new LinkedList<>();
    Iterator<Node<V>> pathIterator = params.getPathToSplit().iterator();
    while (pathIterator.hasNext()){
        Node<V> node = pathIterator.next();
        subPath.add(node);
        Set<Edge<V>> edges = new HashSet<>(graph.getEdges(node));
        if (pathIterator.hasNext()){
            Iterator<Edge<V>> iterator = edges.iterator();
            while (iterator.hasNext()){
                Edge<V> edge = iterator.next();
                Node<V> previousNode = params.getPathToSplit().getPredecessor(node);
                try {
                    if (previousNode != null && edge.getTarget(node).equals(previousNode)){
                        iterator.remove();
                    }
                } catch (DestinationNotExistsException ignored){
                }
                catch (EdgeException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        if (edges.size() > 1){
            if (subPath.size() > 1){
                paths.add(new Path<>(subPath));
            }
            if (!pathIterator.hasNext()){
                subPath = new LinkedList<>();
                break;
            }
            subPath = new LinkedList<>(Collections.singleton(node));
        }
    }
    if (subPath.size() > 0){
        subPath.add(params.getPathToSplit().iterator().next());
        paths.add(new Path<>(subPath));
    }

    return paths;
}

 

How it works

  1. Init new list of nodes representing the current subpath
  2. For every node of the given path do following steps:
    1. Add the node to the subpath
    2. If the currrent node is not the end node to the following steps:
      1. If the current node has multiple successors:
        1. Add current subpath to the list of found subpaths
        2. If the current node is the end node do the following steps:
          1. Create new empty subpath
          2. If the current subpaths has more than 1 node, add it to the list of found subpaths
          3. Return the list of found subpaths
        3. Create new subpath containing current node as its starting node
  3. If the current subpaths has more than 1 node, add it to the list of found subpaths
  4. Return the list of found subpaths

The GraphWalker-Algorithm

For the circuit simulator I currently work on, I needed an algorithm for finding all paths between two given nodes in a graph. One problem was, that the graph can have loops and its edges are bidirectional, so the algorithm should be able to detect loops. I spent some time searching on google for adequate algorithms but I didn’t find some, so I had to develop it on my own:

public Set<Path<V>> apply(Graph<V> graph, Parameters<V>... parameters) {
    assert parameters.length == 1;
    Parameters<V> params = parameters[0];

    Set<Path<V>> currentPaths = new HashSet<>();
    currentPaths.add(new Path<>(Collections.singletonList(params.getStart())));
    Set<Path<V>> nextPaths = new HashSet<>();
    Set<Path<V>> pathsFound = new HashSet<>();

    while(currentPaths.size() > 0){
        for (Path<V> path : currentPaths){
            Node<V> node = path.getEndNode();

            if (node.equals(params.getEnd())){
                pathsFound.add(path);
                continue;
            }

            for (Edge<V> edge : graph.getEdges(node)){
                Node<V> nextNode;
                try {
                    nextNode = edge.getTarget(node);
                    nextPaths.add(path.attachNode(nextNode));
                } catch (EdgeException | CircularPathException e) {
                }
            }
        }
        currentPaths = nextPaths;
        nextPaths = new HashSet<>();
    }

    return pathsFound;
}

 

How it works

  1. Create an empty set of currently tracked paths
  2. Add the starting node to the set of currently tracked paths
  3. Create an empty set of paths to be tracked in the next iteration
  4. Create an empty set of found paths
  5. While set of currently tracked paths is not empty do following steps:
    1. For each path in the set of currently tracked paths do following steps:
      1. Get the last node of the path
      2. If the last node is the end node, add the current path to the set of found paths and continue with the next path
      3. Get all edges the last node of the path is connected to
      4. For every edge the last node of the path is connected to do following steps:
        1. Get the node of the edge the last node of the path is connected to
        2. If the retrieved node is not yet in the path:
          1. Copy the current path
          2. Add the retrieved node to the new path
          3. Add the new path to the list of paths to be tracked in the next iteration
    2. Assign the set of paths to be tracked in the next iteration to the set of currently tracked paths
    3. Create a new set of paths to be tracked in the next iteration
  6. Return the set of found paths