I was wondering if it would be possible to use B4J to program the Lego Mindstorms EV3 Brick for some time. So, some weeks ago, I finally spend a couple of evenings looking into it. And yes, B4J goes Robotics! It uses a modified LeJOS Firmware.
I upgraded LeJOS to support Java 1.8, which is probably the most technical part of the project. I cannot provide it here, as it depends on your Java version but if you follow the next steps, you can build your own. This is done on a Windows PC:
Upgrading the LeJOS Firmware to use Java 1.8
The following procedure will install the java 8 environment compatible with leJOS 9.0 from windows 7. The only extra tool needed is 7ZIP (a free tool) which can generate tar and gz format. In the following I use a temporary directoyr as F:\temp. Replace it with your own temp directory wherever it appears.
- Go to java site http://www.oracle.com/technetwork/java/ … 82511.html
- Create an account if you dont have one then Accept Licensee agreement and download ejdk-8-xxxxxxx-linux-arm-sflt-xxxxxxxx.tar.gz or the latest java8 jre for EV3.
- Unzip this file in your F:\temp directory. For simpler process you may rename the extracted directory as ejdk8. Run 7zip as administrator!
- Go to directory ejdk8\ejdk1.8.0\bin. Save the file jrecreate.bat. Now right click on jrecreate.bat and select “modify”. Add one first line to the bat file as SET JAVA_HOME=C:\Progra~2\Java\jdk1.8.xxxx. this is where java8 is installed on my system. Program~2 stand for Program Files (x86) but is easier to type.
- Start a command window: Start->All prog->Accessory->commands.
- In this window type in the following commands
F:
cd temp
cd ejdk8\ejdk1.8.0\bin
jrecreate.bat –dest newjre –profile compact2 –vm clientIt should start creating the new jre files in the directory “newjre” under ejdk8\ejdk1.8.0\bin
Wait for the final message.
Close the command window. - With file explorer go to F:\temp\ejdk8\ejdk1.8.0\bin. Copy “newjre” directory back to F:\temp
- Rename the “newjre” directory as something expected by LeJOS such as
ejre-8-b132-linux-arm-sflt - Right click on it. Open with 7ZIP and add to archive. Select tar format. It will create ejre-8-b132-linux-arm-sflt.tar file.
- Right click on tar copy then add archive with gzip format. It will create ejre-8-b132-linux-arm-sflt.tar.gz. You have created the JRE file for java8 expected by EV3.
- Insert your SD card and format it.
- Copy the ejre-8-b132-linux-arm-sflt.tar.gz under the sd card top directory.
- Go to C:\Program Files\leJOS EV3
- Now remove the SD from PV and insert the card into the EV3 brick then power it. Wait for the end of the install (about 10mn).
If anything goes wrong, format again the SD, empty the F:\temp directory and restart at step 3. if it persist try another SD card.
Your brick is ready!
Next I wrote a B4J wrapper for the basics like motors, sensors etc. This project is just a hobby and may grow in the future. But I just wanted to share this first video (badly directed so no Oscars here, unless…)
Obviously, I wanted to test out my code, but I had to build a bot first. Well, I was in for a surprise! It took me over 3 hours to build EV3D4 and I can tell you, I’m not a very patient person so I may have taken some shortcuts in the construction.
What happens in the video:
1. I uploaded the B4J created .jar file to the brick via ssh and I’m ready to start it.
2. After some time, it runs (on the brick shows a disclamer and waits for a key).
3. I disconnect the brick, put it on the ground and press a button on the brick.
4. I programmed the IR sensor so if it sees a wall, it turns away, else it keeps going.
Fun fact is you can use B4J-Bridge.jar on the brick!
This is handy as debugging a Brick is a b*tch. You must have a lot of patience and prepared to restart your brick A LOT. This is not a B4J limitation, just to say how unstable programming a Brick is in general.
Coding is straightforward in B4J (this is all the code I wrote, including turning if it is about to hit a wall):
Sub Process_Globals Private StartTimer As Timer Public EV3 As ABLegoEV3 Public LeftMotor As ABLLargeRegulatedMotor Public RightMotor As ABLLargeRegulatedMotor Public Sensor As ABLIRSensor Public sp As ABLSensorMode Public control As Int = 0 Public distance As Int = 255 End Sub Sub AppStart (Args() As String) LeftMotor.Initialize("B") RightMotor.Initialize("C") LeftMotor.ResetTachoCount RightMotor.resetTachoCount LeftMotor.rotateTo(0) RightMotor.rotateTo(0) LeftMotor.Speed = 400 RightMotor.Speed = 400 LeftMotor.Acceleration = 800 RightMotor.Acceleration = 800 Log("starting sensor") Sensor.Initialize("S4") sp = Sensor.DistanceMode IntroMessage StartTimer.Initialize("StartTimer", 100) StartTimer.Enabled = True StartMessageLoop End Sub Sub StartTimer_Tick ' read the sensor Dim sample(sp.sampleSize) As Float control = Sensor.getRemoteCommand(0) sp.fetchSample(sample, 0) distance = sample(0) Log("Control: " & control & " Distance: " & distance) If distance < 70 Then Log("A wall!") EV3.Button.LEDPattern(2) LeftMotor.rotate2(-180, True) ' start Motor.B rotating backward RightMotor.rotate(-180) ' rotate C farther To make the turn If Bit.And(DateTime.Now, 1) <> 0 Then LeftMotor.rotate2(-180, True) ' start Motor.B rotating backward RightMotor.rotate(180) ' rotate C farther To make the turn Else RightMotor.rotate2(-180, True) ' start Motor.B rotating backward LeftMotor.rotate(180) ' rotate C farther To make the turn End If Else Log("Let's walk") EV3.Button.LEDPattern(1) LeftMotor.Speed = 400 RightMotor.Speed = 400 LeftMotor.Backward ' my motors are installed inverted on this robot RightMotor.Backward End If End Sub Sub IntroMessage() Dim g As ABLGraphicsLCD = EV3.GraphicsLCD g.clear g.drawString("Bumper Car Demo", 5, 0, 0) g.Font = g.Font.SmallFont g.drawString("Demonstration of the Behavior", 2, 20, 0) g.drawString("subsumption classes. Requires", 2, 30, 0) g.drawString("a wheeled vehicle with two", 2, 40, 0) g.drawString("independently controlled", 2, 50, 0) g.drawString("motors connected to motor", 2, 60, 0) g.drawString("ports B and C, and an", 2, 70, 0) g.drawString("infrared sensor connected", 2, 80, 0) g.drawString("to port 4.", 2, 90, 0) ' Quit GUI button: g.Font = g.Font.SmallFont Dim y_quit As Int = 100 Dim width_quit As Int = 45 Dim height_quit As Int = width_quit/2 Dim arc_diam As Int = 6 g.drawString("QUIT", 9, y_quit+7, 0) g.drawLine(0, y_quit, 45, y_quit) ' top line g.drawLine(0, y_quit, 0, y_quit+height_quit-arc_diam/2) ' left line g.drawLine(width_quit, y_quit, width_quit, y_quit+height_quit/2) ' right line g.drawLine(0+arc_diam/2, y_quit+height_quit, width_quit-10, y_quit+height_quit) ' bottom line g.drawLine(width_quit-10, y_quit+height_quit, width_quit, y_quit+height_quit/2) ' diagonal g.drawArc(0, y_quit+height_quit-arc_diam, arc_diam, arc_diam, 180, 90) ' Enter GUI button: g.fillRect(width_quit+10, y_quit, height_quit, height_quit) g.drawString2("GO", width_quit+15, y_quit+7, 0,True) EV3.Button.WaitForAnyPress If (EV3.Button.ESCAPE.isDown()) Then ExitApplication2(0) End If g.clear End Sub
As I said, this is just for fun. No idea how far this will go. You can download the source code for the B4J library from my Github.
Cheers,
Alwaysbusy