Skip to content

4. seven steps to an Raspberry Pi application

Bernd Schuster edited this page Aug 5, 2014 · 36 revisions

You can learn here:

  • how to install an elbfisch runtime environment on a raspberry pi
  • how the gpio of the raspberry can be accessed using elbfisch vioss (versatile input/output subsystem)
  • how elbfisch modules can synchronize on process events.

HINT: A brief description of more elbfisch features you can find here

1) Prepare your Raspberry Pi:

  • install Raspbian (Debian Wheezy) (get it here)
  • install a Java 1.7 using
root@raspberrypi:/apt-get install oracle-java7-jdk

2) change directory to /usr/local

root@raspberrypi:/#cd /usr/local

3) Download the tarball RaspberryPiSample.tar

4) extract the tarball

root@raspberrypi:/usr/local# tar -xzf ./RaspberryPiSample.tar
A directory named /usr/local/application should show up now with the following contents:

5) change directory to /usr/local/application

root@raspberrypi:/usr/local#cd ./application

6) shortcircuit pin’s 4 and 5 of your Raspberry Pi.

7) start the the shell script

root@raspberrypi:/usr/local/application# ./applicationloop.sh

and look what you get on your console:


16:51:03,898 [INFO:JPac] STARTING
16:51:03,921 [INFO:JPac] awaiting start up signal ...
16:51:04,899 [INFO:main] startCycling requested
16:51:04,908 [INFO:main] startCycling() acknowledged
16:51:04,930 [INFO:JPac] starting up org.jpac.vioss.raspi.gpio.IOHandler(raspigpio:)
16:51:04,984 [INFO:JPac] running in LazyBound mode ...
16:51:05,019 [INFO:MainModule.ReadbackPinModule] started ...
16:51:05,042 [INFO:MainModule.TogglePinModule] started ...
16:51:05,092 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:06,095 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:07,100 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:08,103 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:09,108 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:10,113 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:11,118 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:12,122 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:13,127 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:14,031 [INFO:MainModule.TogglePinModule] delaying toggle ...
16:51:14,133 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:16,143 [INFO:MainModule.ReadbackPinModule] !!!!!!!!!!!!!! toggle time exceeded !!!!!!!!!!!!!!!!!!!!!
16:51:16,146 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:17,146 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:18,149 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:19,152 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:20,157 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)
16:51:21,161 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = false)
16:51:22,165 [INFO:MainModule.ReadbackPinModule] pin #5: LogicalInput(MainModule.ReadbackPinModule.RaspiInputPin05 = true)

If you get something like shown above: Congratulation, your raspberry application works.

You can stop it by pressing CTRL-C:


^C16:51:22,949 [INFO:ShutdownHook] shutdown requested. Informing jPac ...
16:51:22,967 [INFO:JPac] storing histogramm informationen to ./data/histogramm.csv
16:51:22,989 [INFO:JPac] shutting down modules ...
16:51:22,996 [ERROR:MainModule.ReadbackPinModule] shutting down ... 
16:51:23,002 [INFO:JPac] ... shutting down modules done
16:51:23,005 [INFO:JPac] shutting down ...org.jpac.vioss.raspi.gpio.IOHandler(raspigpio:)
16:51:23,010 [INFO:JPac] cycle mode               : LazyBound
16:51:23,014 [INFO:JPac] cycle time               : 100000000 ns
16:51:23,017 [INFO:JPac] min remaining cycle time : 89637242 ns (89%)
16:51:23,019 [INFO:JPac] max remaining cycle time : 99249017 ns (99%)
16:51:23,022 [INFO:JPac] SHUTDOWN COMPLETE
16:51:23,110 [INFO:ShutdownHook] shutdown complete

Let’s take a closer look at our s(a)imple elbfisch application.

It consists of 4 Java classes:

  • Sample is the formal main program which is used to instantiate the elbfisch modules
  • MainModule is the main module of this elbfisch application. It instantiates the following modules.
  • TogglePinModule simply toggles gpio pin#4 of our raspberry pi once a second
  • ReadbackPinModule simply waits for gpio pin#5 to toggle and generates an apropriate log message

All elbfisch modules run on separate threads.

Let’s begin with the elbfisch module TogglePinModule.



/**
 * PROJECT   : Elbfisch - java process automation controller (jPac)
 * MODULE    : TogglePinModule.java
 * VERSION   : -
 * DATE      : -
 * PURPOSE   : 
 * AUTHOR    : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
 * REMARKS   : -
 * CHANGES   : CH#n <Kuerzel> <datum> <Beschreibung>
 *
 * This file is part of the jPac process automation controller.
 * jPac is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jPac is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the jPac If not, see <http://www.gnu.org/licenses/>.
 */

package raspberry;

import java.net.URI;
import java.net.URISyntaxException;
import org.jpac.AbstractModule;
import org.jpac.InconsistencyException;
import org.jpac.InputInterlockException;
import org.jpac.Module;
import org.jpac.OutputInterlockException;
import org.jpac.PeriodOfTime;
import org.jpac.ProcessException;
import org.jpac.SignalAlreadyExistsException;
import org.jpac.WrongUseException;
import org.jpac.vioss.raspi.gpio.LogicalOutput;

/**
 *
 * @author berndschuster
 */
public class TogglePinModule extends Module{
    
    private LogicalOutput pin4;
    
    public TogglePinModule(AbstractModule containingModule, String identifier) throws SignalAlreadyExistsException, InconsistencyException, WrongUseException, URISyntaxException{
        super(containingModule, identifier);
        pin4 = new LogicalOutput(this, "RaspiOutputPin04", new URI("raspigpio:/4"));
    }
    
    @Override
    protected void work() throws ProcessException {
        PeriodOfTime toggleTime         = new PeriodOfTime(1 * sec);//instantiate a period of time event (1 s)
        PeriodOfTime extendedToggleTime = new PeriodOfTime(3 * sec);//instantiate a period of time event (1 s)
        int          cycleCounter       = 0;
        Log.info("started ...");
        pin4.set(false);
        do{
            if (++cycleCounter % 10 != 0){
                toggleTime.await();//wait for 1 second
            }
            else{
                Log.info("delaying toggle ...");
                extendedToggleTime.await();
            }
            pin4.set(!pin4.is(true));
            //Log.info("toggled " + pin4);
        }
        while(true);    
    }

    @Override
    protected void preCheckInterlocks() throws InputInterlockException {
    }

    @Override
    protected void postCheckInterlocks() throws OutputInterlockException {
    }

    @Override
    protected void inEveryCycleDo() throws ProcessException {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

In it’s constructor it instantiates an LogicalOutput instance named pin4:
It is addressed by the uri “raspigpio:/4” which is used by elbfisch vioss (versatile input/output subsystem) to locate it.

pin4 = new LogicalOutput(this, "RaspiOutputPin04", new URI("raspigpio:/4"));

The main activity is done inside the work() method. It first instantiates the process event PeriodOfTime which can be used by an elbfisch module to delay a certain activity for given amount of time (here 1 second). Then it runs into a loop in which simply toggles the pin every second.

pin4.set(!pin4.is(true));

(Every ten’th second the toggle is delayed for another 2 seconds (extendedToggleTime).)

The elbfisch module ReadBackPinModule simply waits for gpio pin#5 to toggle and log’s this event.



/**
 * PROJECT   : Elbfisch - java process automation controller (jPac)
 * MODULE    : ReadBackPinModule.java
 * VERSION   : -
 * DATE      : -
 * PURPOSE   : 
 * AUTHOR    : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
 * REMARKS   : -
 * CHANGES   : CH#n <Kuerzel> <datum> <Beschreibung>
 *
 * This file is part of the jPac process automation controller.
 * jPac is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jPac is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the jPac If not, see <http://www.gnu.org/licenses/>.
 */

package raspberry;

import java.net.URI;
import java.net.URISyntaxException;
import org.jpac.AbstractModule;
import org.jpac.EventTimedoutException;
import org.jpac.InconsistencyException;
import org.jpac.InputInterlockException;
import org.jpac.Module;
import org.jpac.NextCycle;
import org.jpac.OutputInterlockException;
import org.jpac.PeriodOfTime;
import org.jpac.ProcessException;
import org.jpac.ShutdownRequestException;
import org.jpac.SignalAlreadyExistsException;
import org.jpac.WrongUseException;
import org.jpac.vioss.raspi.gpio.LogicalInput;
import org.jpac.vioss.raspi.gpio.LogicalOutput;

/**
 *
 * @author berndschuster
 */
public class ReadBackPinModule extends Module{
    
    private LogicalInput  pin5;
    
    public ReadBackPinModule(AbstractModule containingModule, String identifier) throws WrongUseException, URISyntaxException, SignalAlreadyExistsException, InconsistencyException{
        super(containingModule, identifier);
        pin5 = new LogicalInput(this, "RaspiInputPin05", new URI("raspigpio:/5"));
    }
    
    @Override
    protected void work() throws ProcessException {
        Log.info("started ...");
        try{
        pin5.becomesValid().await();//wait, until the signal pin5 becomes valid
        do{
            try{
            Log.info("pin #5: "  + pin5);
            pin5.toggles().await(2 * sec);//wait, until pin5 changes it's state
            }
            catch(EventTimedoutException exc){
                Log.info("!!!!!!!!!!!!!! toggle time exceeded !!!!!!!!!!!!!!!!!!!!!");
            }
        }
        while(true);    
        }
        catch(ShutdownRequestException exc){
                Log.error("shutting down ... ");            
        }
    }

    @Override
    protected void preCheckInterlocks() throws InputInterlockException {
    }

    @Override
    protected void postCheckInterlocks() throws OutputInterlockException {
    }

    @Override
    protected void inEveryCycleDo() throws ProcessException {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}

In it’s constructor it instantiates the LogicalInput instance named pin5:
It is addressed by the uri “raspigpio:/5”.

pin5 = new LogicalInput(this, "RaspiInputPin05", new URI("raspigpio:/5"));

The main activity is again done inside the work() method. It first wait’s, until the vioss has
read in the pin the first time

pin5.becomesValid().await();

and afterwards, in a loop, it wait’s for pin#5 to toggle

pin5.toggles().await(2 * sec);

If the toggle does not occur within 2 second’s a EventTimedoutException is thrown.

As pin#4 and pin#5 are shortcircuited, every time the TogglePinModule changes the state of pin#4 the ReadBackPinModule is invoked by the above mentioned toggles event.

Try out, what happens, if you break the shortcircuit

The MainModule in this application is trivial. It instantiates the two modules mentioned above and, in its work() method, it simply waits for an event, which can not ocurr (ImpossibleEvent())
Have a brief look at it:



/**
 * PROJECT   : Elbfisch - java process automation controller (jPac)
 * MODULE    : MainModule.java
 * VERSION   : -
 * DATE      : -
 * PURPOSE   : 
 * AUTHOR    : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
 * REMARKS   : -
 * CHANGES   : CH#n <Kuerzel> <datum> <Beschreibung>
 *
 * This file is part of the jPac process automation controller.
 * jPac is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jPac is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the jPac If not, see <http://www.gnu.org/licenses/>.
 */

package raspberry;

import java.net.URI;
import java.net.URISyntaxException;
import org.jpac.ImpossibleEvent;
import org.jpac.InconsistencyException;
import org.jpac.InputInterlockException;
import org.jpac.Module;
import org.jpac.OutputInterlockException;
import org.jpac.ProcessException;
import org.jpac.SignalAlreadyExistsException;
import org.jpac.WrongUseException;
import org.jpac.vioss.modbus.LogicalInput;
import org.jpac.vioss.modbus.LogicalOutput;

/**
 *
 * @author berndschuster
 */
public class MainModule extends Module{

    public MainModule() throws SignalAlreadyExistsException, InconsistencyException, WrongUseException, URISyntaxException{
        super(null,"MainModule");
    }
    
    @Override
    protected void work() throws ProcessException {
        new ImpossibleEvent().await();
    }

    @Override
    public void start(){
        try{
            //invoke my containing modules
            new TogglePinModule(this,"TogglePinModule").start();
            new ReadBackPinModule(this,"ReadbackPinModule").start();
            //then start myself
            super.start();
        }
        catch(Exception exc){
            Log.error("Error: ", exc);
        }
        
    }
    @Override
    protected void preCheckInterlocks() throws InputInterlockException {
    }

    @Override
    protected void postCheckInterlocks() throws OutputInterlockException {
    }

    @Override
    protected void inEveryCycleDo() throws ProcessException {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

The Sample class serves as the main program by simply instantiating the MainModule and starting it:



/**
 * PROJECT   : Elbfisch - java process automation controller (jPac)
 * MODULE    : Sample.java
 * VERSION   : -
 * DATE      : -
 * PURPOSE   : 
 * AUTHOR    : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
 * REMARKS   : -
 * CHANGES   : CH#n <Kuerzel> <datum> <Beschreibung>
 *
 * This file is part of the jPac process automation controller.
 * jPac is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jPac is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the jPac If not, see <http://www.gnu.org/licenses/>.
 */

package raspberry;

import org.jpac.Module;

/**
 *
 * @author berndschuster
 */
public class Sample {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args){
       boolean handles = false;
       try{
            Module mod      = new MainModule();
            mod.start();
            Thread.sleep(2000);
            while(mod.isAlive()){Thread.sleep(100);};     
       }
       catch(Exception exc){
           exc.printStackTrace();
       }
    }
}

Clone this wiki locally