Reading Pins from Arduino

I'm trying to lean the framework for this wonderful robot lab, and I'm stuck trying to read the pins from an Arduino. How do I access and read the Arduino pins in my program:

package org.myrobotlab.opencv;

import org.myrobotlab.service.Arduino;
import org.myrobotlab.service.Clock;
import org.myrobotlab.service.Clock.PulseDataType;
import org.myrobotlab.service.GUIService;
import org.myrobotlab.service.Log;
import org.myrobotlab.service.Runtime;
import org.myrobotlab.service.Speech;
import org.myrobotlab.service.data.Pin;

public class MainTest {

    public MainTest() {
        System.out.println("Started");
        Log log = (Log) Runtime.createAndStart("log", "Log");
        GUIService gui = (GUIService) Runtime.createAndStart("gui", "GUIService");
        Arduino arduino = (Arduino) Runtime.createAndStart("ard", "Arduino");
        Speech speech = (Speech) Runtime.createAndStart("speech", "Speech");
        Clock clock = (Clock) Runtime.createAndStart("clock", "Clock");
        log.startService();
        arduino.startService();
        clock.startService();
        speech.startService();
        gui.display();
        clock.display();
        log.display();
        speech.display();
        clock.pulseDataString = "test";
        clock.setPulseDataString("test");
        clock.setPulseDataType(PulseDataType.string);
        clock.startClock();
        clock.addListener("pulse", "log", "log");
        arduino.addListener("publishPin", "log", "log", Pin.class);
        arduino.setSerialDevice("/dev/ttyACM0", 57600, 8, 1, 0);
        arduino.connect();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        while (true) {
            try {

                // ################# Doesn't seem to work here.
                // ###################
                for (Pin p : arduino.getPinList()) {
                    System.out.print(p.value + " ");
                }
                System.out.println();
                arduino.digitalWrite(8, 1); // turn on LED
                arduino.digitalWrite(9, 0); // turn on LED
                Thread.sleep(500);
                arduino.digitalWrite(8, 0); // turn on LED
                arduino.digitalWrite(9, 1); // turn on LED
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new MainTest();
    }

}

 

GroG's picture

Hello and Welcome Raver1975 !!!

Wow, this is exciting..  a Java guru !

I re-edited your post because I like syntax highlighting..
There are quite a few ways to preserve high-lighting & formatting 

  • online formater - copy / paste - http://tohtml.com/java/ 
  • java2html - plugin for eclipse - http://www.java2html.de/eclipse.html
  • block-quote in the editor here - (one which looks like 2 quotes - preserves some formatting - not tabs though)
  • and their is even a way to do it with javascript through the editor - but the details escape me - although at some point I'll hook it up with a "source button"

Now on the good stuff !
Make note there is also a Jython editor embedded into MyRobotLab (MRL) - in case you would like to experiment that way.

The first thing which comes to mind is MRL is a collection of services - when a service is installed (like Arduino) - dependences are downloaded and put into the appropriate locations.  The dependencies can include a variety of files, jars, and sometimes native binaries. 

If your trying to use the Arduino service in the debugger, the Arduino service still needs to be installed AND there has to be a JVM argument to set the java.libarary.path

 -Djava.library.path="libraries/native/x86.64.windows"

To get things up and running quickly - you'd want to set the debug configurations of org.myrobotlab.service.Runtime to this..

This starts MRL Runtime service with a GUIService & a Python service.  From that point Arduino can be easily configured from the GUI.

GUIService is currently the only one with a functional display (although there are plans for others) so display only needs to be called on the GUIService.

If you can describe what you want to do - e.g. make a Java programs which sends data to and from the Arduino I might be able to better assist you.

WooHoo ! - also change your avatar - you are not a scared gopher ! :D

raver1975's picture

Hello

Thanks for posting the above, it's a lot of good information. Myrobotlab is some fine quality software.

I've got all the dependencies figured out, my program starts up and my arduino lights will start blinking from the while loop.

I can use the arduino GUI to set a pin as an input pin, and then watch the oscilloscope change as I click a switch attached to the input pin.

The code that doesn't seem to work for me is this:

 

                for (Pin p : arduino.getPinList()) {
                    System.out.print(p.value + " ");
                }

It always prints out the pins as "0" no matter what I do.

Can you tell me how I would change the above program to poll digital pin 7 and print out a message when the input goes to 1?

Or do I use a sensor, and triggers? 

Do you have an example?

How would you go about polling an arduino input pin from Java, and doing something when a switch is pressed?

Also in the Myrobotlab source code, in your OpenCVGUI class you filter out "DC1394FrameGrabber" and "FireflyCaptureFrameGrabber" in the input video list, but those are the cameras I have, so I had to track down the problem and change your source to allow those.

 

 

 

GroG's picture

These are all good questions..

I'm glad you made considerable progress.  

The short answer is the pinList is really for other services to determine what type of pin configuration a particular Arduino has.  For example, the Arduino Mega's pin number and position of pwm pins is much different than a Uno.

But, I think it would be a good idea if you could poll these pins.

MyRobotLab (MRL) uses a messaging framework, and you typically don't need to poll information.  Instead, you subscribe to messages your interested in.   If you look into the ArduinoGUI class which represents a GUI view of the Arduino - you'll see the following 

 

subscribe("publishPin", "publishPin", Pin.class);

 

This subscribes the GUIService publishPin method to the Arduino's publishPin method (with a parameter of Pin.class)

You'll see this

 

public void publishPin(Pin pin) {

method in the ArduinoGUI get called whenever a pin changes state on the Arduino.

So most event driven data is handled with publish / subscribe methods much like Event handling in Java.

As for the OpenCV frame grabbers, I have taken the filters off, thanks ;)

Services can easily publish, subscribe or unsubscribe to messages, however, your question made me aware that it is not as easy to do this with a simple MainTest class.  When I have a little time, I'll look into how to make this very simple.

Thanks for your interest.

 

 

raver1975's picture

My First MRL Robot

Thanks for that tip GroG, that's what I needed to get things rolling. Got any other secrets to share?

Have you ever heard of Dr. Java? It has a cool API for dynamically running Java code, kinda like a Java interpreter, but the cool thing is that it use reflection to analyze running instances of Java classes, and you can dynamically alter variables or call methods of a running Java program. You type Java code into a interpreter window and it executes immediately. That would be awesome when a robot can change it's own source code.

I'm running a Programmer's workshop for our Maker Space tonight, and I'm going to show off how cool MRL is to everyone.

Can youa dd a
public boolean digitalRead(int pin){}
method to the arduino service?
Something that will poll the pins and return the value immediately.
That would be handy.

Here is the code for my first robot:

 

First, I copied Log.java as CustomLog.java and added this simple method in that new class to catch the Pin messages.

 

public void pinreader(Pin p) {
    //process Pin message
    System.out.println(p);
}

Then here is my main class:

 

import org.myrobotlab.service.Arduino;
import org.myrobotlab.service.CustomLog;
import org.myrobotlab.service.GUIService;
import org.myrobotlab.service.Log;
import org.myrobotlab.service.Runtime;
import org.myrobotlab.service.Speech;
import org.myrobotlab.service.data.Pin;

public class PainRobot {
    public static Speech speech;
    public static Arduino arduino;
    public static Log log;

    public PainRobot() {
        System.out.println("Started");
        log = (Log) Runtime.createAndStart("log", "Log");
        GUIService gui = (GUIService) Runtime.createAndStart("gui",
                "GUIService");
        arduino = (Arduino) Runtime.createAndStart("ard", "Arduino");
        CustomLog rt = (CustomLog) Runtime.createAndStart("rt", "CustomLog");
        speech = (Speech) Runtime.createAndStart("speech", "Speech");
        log.startService();
        rt.startService();
        arduino.startService();
        arduino.setSerialDevice("/dev/ttyACM0", 57600, 8, 1, 0);
        arduino.connect();
        while (!arduino.isRunning()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            System.out.println("wait a second!");
        }

        arduino.addListener("publishPin", "log", "log", Pin.class);
        arduino.addListener("publishPin", "rt", "pinreader", Pin.class);

        arduino.digitalReadPollingStart(7);
        int b = 0;
        while (arduino.isRunning()) {
            arduino.digitalReadPollingStart(7);

            arduino.digitalWrite(8, b);
            arduino.digitalWrite(9, 1 - b);
            b = 1 - b;

            try {
                Thread.sleep(CustomLog.runflag ? 50 : 500);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            arduino.digitalReadPollingStop(7);
        }
    }

    public static void main(String[] args) {
        new PainRobot();
    }

}

You press a button on an arduino, and it flickers some LED's and swears. I'm going to try running MRL on my Raspberry Pi computer. I'll let you know how it works.

GroG's picture

That was fun !

No, I haven't heard of DrJava - but I'm definately going to check it out.  I've always been interested of code which writes code.  

You inspired me to make some needed updates.  I was flummoxed a little while, trying to think what the easiest way would be to interface MRL with non-MRL (non-Service) code.  (Just so you know a "Service" is the basic building block of MRL -  just in case you ever get the inkling to make some extremely cool Service)

I finally remembered I had a "Proxy" service - and fixed it up appropriately.  The Proxy service allows a gateway to exist between the MRL framework and any Java code.  Here is your example retrofitted with one.

For kicks, I fixed the pinList returned by getPinList - the publishPin event now updates the pinList's value..

 

package org.myrobotlab.client;

import org.myrobotlab.framework.Message;
import org.myrobotlab.framework.MessageListener;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.LoggingFactory;
import org.myrobotlab.service.Arduino;
import org.myrobotlab.service.Clock;
import org.myrobotlab.service.GUIService;
import org.myrobotlab.service.Log;
import org.myrobotlab.service.Proxy;
import org.myrobotlab.service.Runtime;
import org.myrobotlab.service.data.Pin;

public class MainTest implements MessageListener {
    
    private int cnt;

    /**
     * "receive" is the main gatway for all MRL messages into your application
     * you can subscribe to all the other services's methods you would like and they
     * will come to your application through this method.
     */
    @Override
    public void receive(Message msg) {
        System.out.println(String.format("incoming msg %s.%s --> %s.%s", msg.sender, msg.sendingMethod, msg.name, msg.method));
        if (msg.method.equals("ourData"))
        {
            Pin pin = (Pin)msg.data[0];
            System.out.println(String.format("pin event pin %d from %s is now value %d", pin.pin, pin.source, pin.value));
        }// else if (msg.method.equals("otherMethod"))
        {
            // handle other subscriptions methods here...
        }    
    }

    public MainTest() {
        
        // make and start an Arduino
        Arduino arduino = new Arduino("arduino");
        arduino.startService();
        // connect default 8 N 1 to serial device
        arduino.setSerialDevice("/dev/ttyACM0"); 
        //arduino.setSerialDevice("COM10");
        //arduino.setBoard("diecimila");
        arduino.connect();
        
        // make and start a Proxy
        Proxy proxy = new Proxy("myApp");
        proxy.startService();
        
        // add this class so it can receive any messages sent to it
        proxy.addMessageListener(this);
        
        // subscribe to the methods/messages we are interested in
        // arduino.publishPin(Pin) --- is sent to us with msg.method name = "ourData"
        proxy.subscribe("publishPin", arduino.getName(), "ourData", Pin.class);
        arduino.digitalWrite(13, 1); 
        
        // start a gui if you want
        GUIService gui = new GUIService("gui");
        gui.startService();
        gui.display();

        while (cnt < 100) {
            ++cnt;
            try {

                // ################# Works Now ;)
                // ###################
                for (Pin p : arduino.getPinList()) {
                    System.out.print(p.value + " ");
                }
                System.out.println();
                arduino.digitalWrite(13, 1); // turn on LED
                arduino.digitalWrite(9, 0); // turn on LED
                Thread.sleep(500);
                arduino.digitalWrite(8, 0); // turn on LED
                arduino.digitalWrite(9, 1); // turn on LED
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        // when you are done
        Runtime.releaseAll();
    }

    public static void main(String[] args) {
        new MainTest();
    }

}
GroG's picture

Important note

I put all these updates into the bleeding edge - you can check out HEAD from svn if you'd like - or if your running it outside the debugger with a gui

Help -> About -> I feel lucky, give me the bleeding edge

This will replace the myrobotlab.jar with the latest posted on google.

Hope it works for you !

Let us know how the Maker workshop goes :D

raver1975's picture

Here's a video of my first

Here's a video of my first MRL robot in action:

http://www.youtube.com/watch?v=xCAs1toRWds

 

 

I compiled the jar file and successfully ran it on the Raspberry Pi, but the Speech synthesis module plays back the speech too slowly. The Arduino module works great.

Here is the old version of dynamicjava, it's easier to use than the Dr. Java team's fork. The Dr. Java team changed the code somewhat, but documentation is sparse.
http://old.koalateam.com/djava/

here is the original code from the above site:
http://dl.dropbox.com/u/19401902/DynamicJava-1.1.5-src.zip
http://dl.dropbox.com/u/19401902/DynamicJava-1.1.5.zip

Oryou can try to use the new dynamicjava package from Dr. Java's team, but I found it be harder to use.
https://drjava.svn.sourceforge.net/svnroot/drjava/trunk/dynamicjava/

I can try to integrate dynamicjava myself into MRL after I become more familiar with your codebase.
A self Java code modifying and evolving module would be awesome.

 

 

GroG's picture

Ha !

I embedded your video in the comment - (very last buton on the bottom row - copy paste embed from youtube)

Holy Mother of God ! ;)

That's great..  And it's great you got it running on a Raspberry Pi - For giggles you "might" want to try connecting a MRL instance on the RasPi & an MRL instance on the computer.  MRL was made to work like a distributed system .. I haven't tried it for a while - it used to work (I swear)

The remote system has to load a RemoteAdapter service.

The other instance can connect to it with System->connect .

Sometimes there are naming issues - but all that can be adjusted in the startup scripts.

Heh, just tried it and I didn't get the results I was expecting..    I'm probably filtering them...
If you can imagine, this is could have great potential - many MRL instances on many devices - all sharing info and utilizing each others resources..  A happy friendly world !  I digress, but the reason I brought it up was I used it to control the MRL instance on my RasPi - because I ran it headless (wanted to save memory on the Ras) - but I controlled it with a MRL GUI on the PC ..  I'll get back to it soon.  Let me know if you might be interested in this aspect..

Ya, I'd like to investigate the DrJava...

As a segue, you might already be aware of the Python/Jython Service - It's a embedded scripting engine which can call any Java code.  So, you could can create a service or application which writes Jython and sends it to the script engine (Robot producing its own code :)

Just for curiousity are you focused on a current project and seeing if MRL can help, or are you exploring?

GroG's picture

Here's a bit of

Here's a bit of it...

http://myrobotlab.org/content/mrl-pc-rasberry-pi-streaming-data-now

If you notice on the GUI tab (this is running on my PC) 

  • The  Runtime Service MRL93512
  • GUI
  • Jython Script Engine service

are running on my PC, but the Arduino, RasPi and RemoteAdapter are running on the Raspberry Pi

The tab color designates remote services..
Also the Runtime Service on the RasPi was named "RasPi" through the startup script 

GroG's picture

Here's a bit of

Here's a bit of it...

http://myrobotlab.org/content/mrl-pc-rasberry-pi-streaming-data-now

If you notice on the GUI tab (this is running on my PC) 

  • The  Runtime Service MRL93512
  • GUI
  • Jython Script Engine service

are running on my PC, but the Arduino, RasPi and RemoteAdapter are running on the Raspberry Pi

The tab color designates remote services..
Also the Runtime Service on the RasPi was named "RasPi" through the startup script 

GroG's picture

Just thought of another

Just thought of another possiblity for a good service - A Raspberry Pi Service - Something which can control of the RaspPi's GPIO - and any other hardware resources...

raver1975's picture

Lots of stuff

MRL was a hit at the coder's meeting, I'll be showing it off again at tomorrow's meeting. I'm the President of our local maker (virtual) space, http://DHMN,net here in Wisconsin. We've got quite a few robot projects going on, We had an award winning "CandyBot", there is version 1 of "ED-209", the Airsoft gun motion tracking autonomous guard turret, an animatronic robot head is in the works, and there is a self driving autonomous car. MRL is going to help a lot.

There's a lot for me to take in all at once with MRL. My background is all Java, but I can stumble around in Python. I don't know how use the JPython interface for Java yet.

I started a Remote on my Rasberry Pi, and I think I connected my PC to the Raspberry Pi(I could see the connection in the remote tab opn the PI) but nothing else seemed to have happened, and I couldn't figure out how to communicate between instances.

I'll keep trying things. I successfully connected my xbox360 controller to a servo motor on an arduino. I know the animatronic head will be greatly improved using a joystick for a controller. I wish there were more tutorials or some videos to help people get started using MRL. It's a lot to take in all at once.

One of my own projects is using OpenCV to produce a stereo depth map from two cameras, but the math overwhelms me at the moment. I write a lot of Artificial Intelligence software, and I'd like to write a Q-learning module for MRL. Q-learning automatically learns the best states of a robot, and the best transitions of those robot states to maximize a reward function. Neural Nets would also be a good addition to MRL, if it's not in there already.

Keep up the good work.

 

GroG's picture

Its great to see an active maker space

MRL is going to help a lot.   That's Great!

There's a lot for me to take in all at once with MRL. My background is all Java, but I can stumble around in Python. I don't know how use the JPython interface for Java yet

I'm pretty new to Python / Jython too - but it works great as a quick scripting interface.  There's a guy at UNCC who is using MRL as a tool in his thesis, he's utilizing the scripting to create state machines.  The state machines drive virtual robots for testing, then he switches real hardware in (like a Roomba)

So Jython is Python completely running in the JVM.  Really, it's just Java (you can access any Java object or method) without Java's syntactic sugar.  The 3 most important things in Python are : Indent, Indent & Indent - if you have an error its probably related to your indention.

I started a Remote on my Rasberry Pi, and I think I connected my PC to the Raspberry Pi(I could see the connection in the remote tab opn the PI) but nothing else seemed to have happened, and I couldn't figure out how to communicate between instances.

Wow, that's great..  I think there is a considerable amount of potential to being distributed, I just need to get back and tweak it again...  If I remember, I think I put in some filtering so that not all Services are shared - maybe too much filtering.  The communication should be seemless, in that whatever you can do locally, you should be able to do remote - for example - the whole "subscribe" and "recieve" messages doesnt look any different if its local versus remote from the developers point of view.

I'll keep trying things. I successfully connected my xbox360 controller to a servo motor on an arduino. I know the animatronic head will be greatly improved using a joystick for a controller. I wish there were more tutorials or some videos to help people get started using MRL. It's a lot to take in all at once.

I'm impressed with your success.  I think good documentation is critical, but I only have a finite amount of time. Time  could spend on improving the code, or time on documentation.  I try to do both, but I know the documentation has suffered.  I'm hoping others might help in creating tutorials - Alessandruino has promised to make a tutorial - although,I think it will be in Italian ;)

One of my own projects is using OpenCV to produce a stereo depth map from two cameras, but the math overwhelms me at the moment.

I've done some work on that too.  Did you use SURF to find corresponding points - or use the correspondance methods in OpenCV ?

I write a lot of Artificial Intelligence software, and I'd like to write a Q-learning module for MRL. Q-learning automatically learns the best states of a robot, and the best transitions of those robot states to maximize a reward function. Neural Nets would also be a good addition to MRL, if it's not in there already.

That would be GREAT !  A Neural Net Service has been on my TODO list for a very long time.  Additionally, there is great demand for a ChatBot (with learning).

I'm a firm believer in "Great software is not made anymore....  It's grown"  I have another project which I've been working on for a long time which is starting to finally take shape.  The build server for MRL is at my house, as part of the continuous integration build, I have unit tests.  I want to do integration testing - and to that end - I want a continuously running MRL instance (which has the latest code) and is continually "learning".  It will begin "objectifying" the room its running in - and send out queries or guesses to identify and label the objects.  The processed data should be online so other people or instances of MRL can use it.  

More to come ;)