More than just bricks… http://thinkbricks.net LEGO MINDSTORMS EV3 robots, LEGO projects, building instructions and programming cool robots. Sun, 13 Mar 2016 13:49:02 +0000 en-GB hourly 1 Using a serial LCD with the Raspberry Pi http://thinkbricks.net/using-a-serial-lcd-with-raspberry-pi-2/ http://thinkbricks.net/using-a-serial-lcd-with-raspberry-pi-2/#respond Sun, 13 Mar 2016 13:42:35 +0000 http://thinkbricks.net/?p=1245

In this little project I use a serial LCD connected to the Rasp Pi serial output to print the current time and IP address for the Pi. It’s a fun little project as it puts together a few pieces; using the Adafruit T-Cobbler Plus, making an inverter circuit and controlling the serial LCD.

 

There are already some good tutorials online on how to use a standard (non-serial) LCD with the Pi. For example, Adafruit has a great tutorial on driving an LCD using the Pi. However I had a BPI-216N serial LCD from Scott Edwards Electronics which uses a simple single-line serial link running at 2400 or 9600 baud to send data from the Pi to the display. Amazingly I bought this unit in 1998 and have had it sitting in a drawer ever since – and it still works perfectly!

 

Using the serial port on the Rasp Pi

The first thing you need to do is disable the serial port console on the Rasp Pi. Why? By default the Pi boots up and creates a serial console on the Rx and Tx lines running at 115200 baud. This is great if you need to log into a Pi that has no screen attached, but we want to use this serial port to send data to the LCD.

The serial console is configured in /boot/cmdline.txt and you simply need to remove the text that says console=ttyAMA0,115200 and save the cmdline.txt file.

The second step is to display the init process in Linux from attempting to connect a tty to the serial console. In older releases of Raspbian the procedure is to edit /etc/inittab, but in the later releases Raspbian has moved to a new way of starting boot services. The command to remove the serial console tty starting is:

sudo systemctl stop serial-betty@ttyAMA0.service

Reboot your Pi and then the serial console is disabled.

Inverting the signal to the LCD

The interesting (or challenging) part about the serial LCD is that it expects inverted TTL as it expects to be connected to an RS232 port, which inverts the polarity of the signal by default. What does this mean? Well if you want to send the letter ‘a’ (decimal character code 97, binary 0110 0001) then you need to flip each bit and send the value 1001 1110 or 158. This is painful to do in software, so the simple solution is to put an inverter between the TxD pin on the GPIO header and the serial input on the LCD.

I did a quick search online and found this schematic for a single-transistor simple inverter made using one transistor and two resistors. I used 1K resistors and a 2N2222 transistor, mainly because I had them sitting on my desk! Note that this circuit does not do level shifting! The Pi GPIO pins operate at 3.3V but most serial devices use 5V. This isn’t a problem for this project as we’re sending data to the LCD so a level shift isn’t needed.

Wiring it all together looks as follows (yes my breadboard work won’t win any prizes!)

 

 

Python Code to print to the LCD

Finally we get to the code itself. It’s actually pretty simple as the serial port does the bulk of the work and the transistor inverter takes care of the logic signals. I set my LCD to work at 9600 baud. I cheated a little to get the IP address by running the hostname command and parsing the output; not pretty but it works.

To learn more about the commands accepted by the LCD read the programmers guide.

# Show the current IP address and date and time
# on the serial LCD attached to the serial port
#
# Mark Crosbie mark@mastincrosbie.com 12/3/16
# http://thinkbricks.net
import serial
 from time import sleep, strftime
 from datetime import datetime
 import commands
ser = serial.Serial(port='/dev/ttyAMA0', baudrate=9600)
 cls = bytearray([254, 1])
 ip_addr = commands.getoutput("hostname -I").split(" ")[0]
def clearscreen():
 ser.write(cls) # clear and reset screen
 sleep(0.01)
def moveTo(line, col):
 pos = line*192 + col
 b = bytearray([254, pos])
 ser.write(b)
 sleep(0.01)
if ser.isOpen():
 while 1:
 clearscreen()
 ser.write(ip_addr)
 moveTo(1,0)
 ser.write(datetime.now().strftime('%d %b %H:%M:%S'))
 sleep(1.0)
]]>
http://thinkbricks.net/using-a-serial-lcd-with-raspberry-pi-2/feed/ 0
Triangular tracked wheel http://thinkbricks.net/triangular-tracked-wheel/ http://thinkbricks.net/triangular-tracked-wheel/#respond Sat, 30 Jan 2016 21:43:00 +0000 http://thinkbricks.net/?p=1240 A small design study for making a triangular wide-tracked wheel driven by a Lego Mindstorms EV3 large servo motor. Two of these on wither side of a robot chassis gives a very cool effect! I also created building instructions as a test of using LDCad.

You can download the building instructions here in PDF format.

The LDraw file is available here.

Here are a few images.

]]>
http://thinkbricks.net/triangular-tracked-wheel/feed/ 0
Face tracking on EV3 using leJOS 0.9.1 http://thinkbricks.net/face-tracking-on-ev3-using-lejos-0-9-1/ http://thinkbricks.net/face-tracking-on-ev3-using-lejos-0-9-1/#respond Sun, 29 Nov 2015 10:54:51 +0000 https://thinkbricks.net/?p=1228 The leJOS 0.9.1 release added the OpenCV vision processing library. What better way to test it than build a face-detecting robot! First step is to figure out how to use the OpenCV libraries on EV3 to detect a face in an image.

It turns out this is really hard to do in practice. Lighting is one of the problems; any strong reflections or highlights in the image and OpenCV will fail to detect the face. The other issue is the processing speed of the EV3; face detection is a CPU-heavy task! The EV3 has a fast processor, but it struggles to do reliable face detection in almost real-time to control a robot. 

Let’s start with a simple example, using the webcam capture code from https://lejosnews.wordpress.com/2015/09/26/opencv-web-streaming/ as a basis to build on. I’m going to assume that you:

How does face-detection work?

First of all, this code will detect a face-shaped object in an image stream, but it won’t distinguish who it is. That is termed face recognition and is a lot harder to do (trust me – I built these systems for a living!) How does OpenCV detect a face? It takes an image and then appliers a series of ‘classifiers’ to it to extract face-like features from the image. If the image contains enough evidence of face-like features then the OpenCV code returns the coordinates of the bounding rectangle around what it thinks is the face.

OpenCV in leJOS 0.9.1 has two types of face classifiers available: Haar classifiers and LBP feature classifiers. The Haar classifiers are slow but more accurate. In my tests the Haar classifier could reliably detect multiple faces against a bright background, but it was slow! So slow that I was seeing detection times of the order of 1 second per frame (i.e. a frame-rate of 1 fps). This is too slow to reliably control a robot’s motion. The LBP feature classifiers are faster, but less accurate. With an LBP feature classifier I can get on the order of 8-10 fps on the EV3 on a 160×120 image from a webcam. The problem is face detection is very unreliable at this frame-rate, with faces rarely detected even when perfectly lit.

For a great overview of OpenCV and tutorials (in C++) of many functions take a look here: http://opencvexamples.blogspot.com/2013/10/face-detection-using-haar-cascade.html

Reading from the webcam

I’m using a cheap webcam plugged into a USB hub plugged into the host port on the EV3. leJOS has native support for webcams since the 0.9.0 release, and with OpenCV that support is now present in the OpenCV library too. 

We start by initialising and opening the camera device. You’ll have to set the image width and height here too. I set it to a very small size of 160×120 pixels. The camera can return larger images, but the bigger the image the slower it is to process on the EV3!

VideoCapture vid = new VideoCapture(0);

vid.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, 160);

vid.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, 120);

vid.open(0);

System.out.println(“Camera open”);   

 

Once the camera has been opened reading from it is as simple as:

Mat frame = new Mat();

vid.read(frame);     

if (!frame.empty()) {

}

A Mat is an OpenCV data structure akin to a matrix – it is like a ‘magic bucket’ that you can store almost any data in for OpenCV to process. 

Detecting faces

The OpenCV library in Java provides the detectMultiScale() function to detect face images. It takes a number of parameters, and you’ll have to play around with the parameters to get it to work reliably. Face detection is more of an art than a science!

The first thing we want to do is convert the colour image from the webcam into a grayscale image, and then equalise the histogram of the image. While OpenCV can process colour images it seems you’ll get more reliable results from a grayscale image.

Mat mRgba=new Mat();  

Mat mGrey=new Mat();  

frame.copyTo(mRgba);  

frame.copyTo(mGrey);  

Imgproc.cvtColor( mRgba, mGrey, Imgproc.COLOR_BGR2GRAY);  

Imgproc.equalizeHist( mGrey, mGrey );                  

 

Then we can actually do the face detection. Drum roll please….

private final String features = “/lbpcascade_frontalface.xml”;

MatOfRect faces = new MatOfRect();

faceDetector = new CascadeClassifier(getClass().getResource(features).getPath());

faceDetector.detectMultiScale(

        mGrey

        faces,

        scaleFactor,

        minNeighbours,

        flags,

        minSize,

        maxSize);

 

I’m using the lbpcascade face detector for this example because it runs quickly on the EV3 CPU and gives reasonable (but not great) accuracy. You will need to copy the file lbpcascade_frontalface.xml from the opencv/data/lbpcascades directory into the same directory on the EV3 as the jar file you are running (usually into /home/lejos/programs).

That’s a lot of parameters. So what do they all mean?

  • mGrey: This is the input frame that we want to detect a face in. In this case it’s the grayscale image.
  • faces: A matrix of rectangles; OpenCV returns each face as a rectangle as the bounding box around where it thinks the face is located. 
  • scaleFactor: how much scaling is applied to the image. The lower the number the more accurate the detection, but as a consequence the slower it goes. I started with a value of 2.0 for scale factor, and then reduced it down to 1.8 to get better accuracy but a reasonable detection time.
  • minNeighbours: controls accuracy. I just leave this at 2
  • flags: leave this at 0
  • minSize: the minimum size for a face. I set this to 20×20 to allow small faces to be detected. 
  • maxSize: the maximum size for a face. I set it to 160×120 in case the face takes up the whole image.

Interpreting the output and Drawing faces

Once you’ve run detectMultiScale() you’ll need to find the faces, if any were detected. But how? Recall the output is stored in the faces matrix, so we convert that into an array and see if it has any elements in it. If it does we iterate over each element, which is a rectangle, and then draw a rectangle on the image frame so we can display it in a web browser.

int numFaces = faces.toArray().length;
if(numFaces > 0) {
  System.out.println(String.format("+++ Detected %s faces", numFaces));
 
  // each rectangle in faces is a face
  Rect[] facesArray = faces.toArray();
  for (int i = 0; i < facesArray.length; i++) {
     Rect rect = facesArray[i];
Point center= new Point(rect.x + rect.width*0.5, rect.y + rect.height*0.5 );   
Core.rectangle(frame, rect.tl(), rect.br(), new Scalar(0, 255, 0, 255), 2);
  }

What does the output look like?

I opened up a web browser and connected to my EV3 on the wifi. The images look look like this (yes I usually look like that as I’m trying to watch the screen while holding my head still :)

Bounding rectangle on face capture

As I mentioned face detection is very sensitive to lighting and background in an image. In this case I had to move the camera so the skylight above my head wasn’t in the image. At night I found that the lights in the room were creating highlights which confused the camera. An ideal lighting setup is to have a dull matt background with soft lights coming from behind the camera at your face.

Putting it all together

As always you can get the source code on my github account: https://github.com/markcrosbie/lejos_projects/tree/master/OpenCVTesting/src. I’ve added a quick way to play around with the minNeighbours, scaleFactor and classifier type parameters on the command line. You can run the code as 

jrun -cp HTTPFaceDetect.jar HTTPFaceDetect <minNeighbours> <scale> <l/h>
for example
jrun -cp HTTPFaceDetect.jar HTTPFaceDetect 1 2 l

Will give very fast but not accurate detection, whereas:

jrun -cp HTTPFaceDetect.jar HTTPFaceDetect 1 1.1 h

Will be very accurate using a Haar classifier, but will be very (very) slow on the EV3. Experiment and see what works for you.

]]>
http://thinkbricks.net/face-tracking-on-ev3-using-lejos-0-9-1/feed/ 0
Time-lapse video using EV3 and webcam http://thinkbricks.net/time-lapse-video-using-ev3-and-webcam/ http://thinkbricks.net/time-lapse-video-using-ev3-and-webcam/#respond Tue, 07 Jul 2015 13:33:01 +0000 http://thinkbricks.net/?p=1215

I wanted to try making a home surveillance project using my webcam and EV3 sending images into Dropbox. But how to put the obvious time and date stamp on the images? It turns out this is really easy to do using the Graphics2D Java class! A short tutorial on how to do this…

Java provides the Graphics2D class to do simple image manipulation natively. The nice thing about working with leJOS is that you can take advantage of all the existing Java classes in your code that runs on the EV3.

I used my previous code and added a call to the Graphics2D library to overlay the date and time. The thing to remember here is that you have to account for the font size when choosing the x,y location to place the text.

/**
    * Add overlay text with the current UTC date and battery voltage level onto the image
    * Text colour, font and size can be adjusted below
    * 
    * @param old Original image captured from the camera
    * @return new BufferedImage that contains the original image with text overlay
    */
   private BufferedImage addTextOverlay(BufferedImage old) {
       int w = old.getWidth();
       int h = old.getHeight();
       BufferedImage img = new BufferedImage(
               w, h, BufferedImage.TYPE_INT_RGB);
       Graphics2D g2d = img.createGraphics();
       g2d.drawImage(old, 0, 0, null);
       g2d.setPaint(Color.red);
       g2d.setFont(new Font("Serif", Font.BOLD, 15));
       
       // Get the current system date and time in UTC
       Date d = new Date(System.currentTimeMillis());
       String s = "" + d.toString();
       FontMetrics fm = g2d.getFontMetrics();
       int x = img.getWidth() - fm.stringWidth(s) - 5;
       int y = fm.getHeight();
       g2d.drawString(s, x, y);

       // Get the current battery level in mV
       s = "B: " + Battery.getVoltageMilliVolt() + " mV";
       x = img.getWidth() - fm.stringWidth(s) - 5;
       g2d.drawString(s, x, h - y - 5);
       
       g2d.dispose();
       return img;
   }

 

The full code is here: https://github.com/markcrosbie/lejos_projects/tree/0eb43b00e9d8b0bab6bd985ff6d663d02907db3b/SurveillanceCam

I pointed the webcam out of a window in the morning and left the EV3 running on battery power for the day. I was curious how long the battery would last for! It turns out about 7 hours is the answer. After running for that long I had over 2500 images in my Dropbox directory, which I then stitched together into a timelapse video. Cool!

]]>
http://thinkbricks.net/time-lapse-video-using-ev3-and-webcam/feed/ 0
Webcam + leJOS + Dropbox = wow! http://thinkbricks.net/webcam-lejos-dropbox-wow/ http://thinkbricks.net/webcam-lejos-dropbox-wow/#comments Sat, 25 Apr 2015 15:29:43 +0000 https://thinkbricks.net/?p=1204

Now that we have my EV3 connected to Dropbox, let’s have some fun. In this project I use a cheap webcam connected to the EV3 to take a photo and upload it into my Dropbox account. It’s a wireless digital camera using the EV3 and Dropbox!

2015-04-25 16.08.27

I recently bought a cheap webcam and USB hub at Frys electronics. This particular webcam (it cost me about $6) uses the RealTek chipset. leJOS 0.9.0 adds webcam support, and you can read more about it in Lawrie’s tutorial here: https://lejosnews.wordpress.com/2014/09/04/webcam-streaming/

I figured I could do one better, and capture files from the webcam, convert them to JPG and then use the Dropbox Core API to upload them into my Dropbox account. Let’s see how to do it!

I’m assuming you’ve connected your EV3 to your Dropbox as I explained in this tutorial.

Accessing the webcam

LeJOS 0.9.0 release added basic webcam support; only one webcam is supported and the images are returned in YUYV format. But that’s enough to have some fun with.  This little program will capture an image from the webcam and convert it to JPG format and then save it into the directory snapshots/with an incrementing filename. For fun you’ll also get a live image preview (in black and white) on the EV3 screen as well!

NewImage

Here I ran the Snapshot.jar from the command line. It reads the access-token.json file we created in the previous tutorial and uses that to authorise access to my Dropbox folder. When I press the ENTER button the code converts the YUYV format into JPG format, saves it to the EV3 SDcard and then uploads to Dropbox using the Dropbox API. The basics of uploading files in Dropbox is explained here: https://www.dropbox.com/developers/core/start/java

NewImage

The picture above shows what the output is – as you capture images they are uploaded into Dropbox and appear in Finder on my Mac always instantly. The images are at a 160×120 resolution as that is the size of the EV3 screen, but the camera supports much higher res images. Behold The Power of the Cloud!

The Code

The Java code is a combination of the leJOS webcam streaming tutorial code and the Dropbox Java tutorial code. Not the prettiest I’ll admit…

import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Locale;

import javax.imageio.ImageIO;

import lejos.hardware.BrickFinder;
import lejos.hardware.Button;
import lejos.hardware.Sound;
import lejos.hardware.ev3.EV3;
import lejos.hardware.lcd.GraphicsLCD;
import lejos.hardware.lcd.LCD;
import lejos.hardware.video.Video;
import lejos.hardware.video.YUYVImage;

import com.dropbox.core.*;
import com.dropbox.core.json.JsonReader;
import com.dropbox.core.util.IOUtil;

/**
 * Use a cheap webcam to take a snapshot and send the image to Dropbox.
 * Requires a Dropbox authorisation token to be created
 * EV3 needs to be connected to the wifi and the webcam connected too.
 * Requires leJOS 0.9.0 release and some setup. 
 * See http://thinkbricks.net/set-up-dropbox-in-lejos-on-the-ev3 for Dropbox-leJOS setup
 * 
 * Press ENTER button to take a photo. You should see it appear in your Dropbox folder
 * 
 * @author mcrosbie
 * http://thinkbricks.net
 * April 2015
 */

public class Snapshot {
   private static final int WIDTH = 160;
   private static final int HEIGHT = 120;
   private static int NUM_PIXELS = WIDTH * HEIGHT;
   private static int FRAME_SIZE = NUM_PIXELS * 2;
   private static final String AUTHFILENAME = "./access-token.json";
   private static final String FILENAME = "snapshots/snapshot_";

   public static void main(String args[]) throws IOException, DbxException {
	   int ret = _main(args);
	   System.exit(ret);
   }
   
   public static int _main(String[] args) throws IOException, DbxException  {
       int frames = 0;
       int threshold;
              
       // Default to access token file if not on cmd line
       String argAuthFile;
	   if (args.length != 1) {
		   argAuthFile = AUTHFILENAME;
	   } else {
		   argAuthFile = args[0];
	   }

       System.out.println("Reading auth info file " + argAuthFile);
       // Read auth info file.
       DbxAuthInfo authInfo;
       try {
           authInfo = DbxAuthInfo.Reader.readFromFile(argAuthFile);
       } catch (JsonReader.FileLoadException ex) {
         System.err.println("Error loading <auth-file>: " + ex.getMessage());
         return 1;
       }
       
       System.out.println("Creating Dropbox client...");

       // Create a DbxClient to make API calls.
       String userLocale = Locale.getDefault().toString();
       DbxRequestConfig requestConfig = new DbxRequestConfig("Snapshot", userLocale);
       DbxClient dbxClient = new DbxClient(requestConfig, authInfo.accessToken, authInfo.host);
 
       System.out.println("Open video camera...");
       // Get the video device and open the stream
       Video video = BrickFinder.getDefault().getVideo();
       video.open(WIDTH, HEIGHT);
     
       // Create the frame buffer to hold the image in
       byte[] frame = video.createFrame();
       BufferedImage img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
       YUYVImage yuyvImg = new YUYVImage(frame, video.getWidth(), video.getHeight());

       GraphicsLCD g = BrickFinder.getDefault().getGraphicsLCD();

       // Keep displaying an image. 
       // Save a file to storage when enter is pressed
       // Escape to exit
       g.clear();
       System.out.println("Starting main capture loop...");
       while (!Button.ESCAPE.isDown()) {
    	   try {
               video.grabFrame(frame);
               
               // Display on the EV3 screen
               threshold = yuyvImg.getMeanY();
               yuyvImg.display(g, 0, 0, threshold);
               
              if (Button.ENTER.isDown()) {
            	  Sound.playTone(500, 100);
                  for(int i=0;i<FRAME_SIZE;i+=4) {
                      int y1 = frame[i] & 0xFF;
                      int y2 = frame[i+2] & 0xFF;
                      int u = frame[i+1] & 0xFF;
                      int v = frame[i+3] & 0xFF;
                      int rgb1 = convertYUVtoARGB(y1,u,v);
                      int rgb2 = convertYUVtoARGB(y2,u,v);
                      img.setRGB((i % (WIDTH * 2)) / 2, i / (WIDTH * 2), rgb1);
                      img.setRGB((i % (WIDTH * 2)) / 2 + 1, i / (WIDTH * 2), rgb2);
                  }
                  
                  // Convert the RGB image into a jpg format
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
                  ImageIO.write(img, "jpg", baos);
                  byte[] jpgImageBytes = baos.toByteArray();

                  String filename = FILENAME+frames+".jpg";
                  System.out.println("Saving image to " + filename);
                  saveImageToFile(baos.toByteArray(), filename);
                  
                  System.out.println("Saving to Dropbox");
                  writeImageToDropbox(dbxClient, baos.toByteArray(), "/"+filename);
                  System.out.println("Done");
                  Sound.beepSequenceUp();
                  
            	  frames++;
              }
              
    	   } catch (IOException ioe) {
	           ioe.printStackTrace();
	           System.out.println("Driver exception: " + ioe.getMessage());
	           Sound.buzz();
	           return 1;
	      }
       }
      video.close();
      g.clear();
      return 0;
   }
   
    /**
    * Save an image file from the webcam to disk
    * 
    * @param img - image byte buffer
    * @param filename - file to store to
    */
   public static void saveImageToFile(byte[] img, String filename) {
	   try {
		   FileOutputStream fos = new FileOutputStream(filename);
		   fos.write(img);
		   fos.close();
	   } catch(IOException ioe) {
           ioe.printStackTrace();
           System.out.println("Driver exception: " + ioe.getMessage());		   
	   }
   }
   
   private static void writeImageToDropbox(DbxClient dbxClient, byte[] img, String dbFilename) 
		   throws DbxException, IOException {
       // Make the API call to upload the file.
       DbxEntry.File metadata;
       try {
    	   metadata = dbxClient.uploadFile(dbFilename, DbxWriteMode.add(), img.length, 
    			   new ByteArrayInputStream(img));
    	   System.out.println("Metadata: " + metadata.toStringMultiline());
       } catch (DbxException ex) {
               System.out.println("Error uploading to Dropbox: " + ex.getMessage());
       }
   }
    
   private static int convertYUVtoARGB(int y, int u, int v) {
       int c = y - 16;
       int d = u - 128;
       int e = v - 128;
       int r = (298*c+409*e+128)/256;
       int g = (298*c-100*d-208*e+128)/256;
       int b = (298*c+516*d+128)/256;
       r = r>255? 255 : r<0 ? 0 : r;
       g = g>255? 255 : g<0 ? 0 : g;
       b = b>255? 255 : b<0 ? 0 : b;
       return 0xff000000 | (r<<16) | (g<<8) | b;
   }

 }
]]>
http://thinkbricks.net/webcam-lejos-dropbox-wow/feed/ 4
Set up Dropbox in leJOS on the EV3 http://thinkbricks.net/set-up-dropbox-in-lejos-on-the-ev3/ http://thinkbricks.net/set-up-dropbox-in-lejos-on-the-ev3/#comments Sat, 25 Apr 2015 14:34:25 +0000 https://thinkbricks.net/?p=1188

NewImage.pngHere’s a quick tutorial to add Dropbox support into a Java program in leJOS 0.9.0. It turned out to be far easier than I thought! Read on to discover how you can easily upload and download files to and from your Dropbox account from the EV3 in leJOS.

Dropbox? On the EV3?

The first thing to realise is that I’m not going to show you how to install the Dropbox helper on your EV3. Instead we’re going to use the Dropbox Core Java SDK to connect our EV3 to your existing Dropbox account (free or pro, doesn’t matter) and then upload and download files into the account.

Dropbox is well known as a cloud file-sync service that ‘just works’. I’ve been using it for years, both as a pro and business user, and the software runs in the background, never complains and just gets on with the business of keeping all of your files in sync. Luckily Dropbox have extended the same simplicity to their SDK; I was amazing at just how easy it is to use the Java SDK in leJOs 0.9.0 to upload images captured from a webcam to my Dropbox account.

The Dropbox team have done a great job explaining how to use the Java SDK in a series of tutorials here: https://www.dropbox.com/developers/core/start/java
Getting ready
There are a few steps to get everything set up, but once you’ve done the setup you won’t have to repeat it. I’m assuming that these things are in place:
  1. You have a Dropbox account
  2. You have Eclipse installed and leJOS plugin installed
  3. You have a wifi equipped EV3 connected onto your home wifi
  4. You are comfortable logging into your EV3 using ssh in the terminal; you’ll need to run a program on the command line to authorise your EV3 to talk to Dropbox.
The basic flow is to import the Dropbox Java SDK into Eclipse, and then use the Dropbox API to creation an authorisation key that allows the EV3 to talk to your Dropbox account.

Step 1: Download the Dropbox Core API

The Java SDK is here: https://www.dropbox.com/developers/core. Download the Zip file and extract it into a folder on your laptop.
NewImage

Step 2: Create a new leJOS project in Eclipse

I’m assuming you have a working leJOS installation and the leJOS Eclipse plugin installed. If not, go to the leJOS website and follow the instructions on the wiki to get everything set up. Let’s call it DropboxSetup for now.

Step 3: Import the Dropbox Jar files from the SDK into your project

Right click on the DropboxDigitalCamera project, select Properties and then choose ‘Java Build Path’. Click ‘Add External JARs…” and navigate to the two JAR files in the dropbox-sdk/lib folder. Import them into the project and your build path should look something like this:
NewImage

Step 4: Create a new Dropbox app

Log into your Dropbox account and then go to the https://www.dropbox.com/developers/apps page and create a new Dropbox app. Make sure you create a Dropbox API app, and give it a name. The name you choose here will be used in your Dropbox/Apps folder when the EV3 uploads and downloads files. This is safer than giving your EV3 access to the all of the files in your Dropbox account.
NewImage

Step 5: Get the app key and app secret

Dropbox uses an app key and secret assigned to your app to create an access token. The access token is what you need to store on the EV3 so that it can authenticate itself to Dropbox and get access to files in your account.
If you click on the app from Step 4 in the App Console, you’ll see the App key and App secret displayed. Copy these values (obviously I’ve blurred the App key for my Dropbox account here).
NewImage

Step 6: Copy the Dropbox JARs onto the EV3

The Dropbox JARs need to be copied onto the EV3. The easiest way to do this is with your file browser, or scp them from your computer to the EV3. I placed the JARs in /home/lejos/programs/lib.

Step 7: Authorise the EV3 to Dropbox, get the auth token

The last step is to log into the EV3 and run a small Java program to connect the EV3 to your Dropbox account and get the authorisation token. The auth token is saved locally on the SDcard in the EV3 and used by all subsequent programs that need to talk to Dropbox.
The code you need to run is based off the Dropbox tutorial. Copy the App key and secret into the code below and then upload it from Eclipse onto the EV3. ssh into your EV3 and run the code below on the command line as follows:
jrun -cp /home/lejos/programs/lib/dropbox-core-sdk-1.7.7.jar:/home/lejos/programs/lib/jackson-core-2.2.4.jar:GetAccessToken.jar GetAccessToken

NewImage

Here is a screenshot of me running the code on my EV3. I’ve blurred out the app key and secret, and the returned authorisation code!

Step 8: You’re done!

That’s it – your EV3 is now authorised to talk to your Dropbox account, and the authorisation token is stored in the file access-token.json on the  EV3. If you lose this file it’s easy to run this program again and re-create it. But don’t share it with anyone, otherwise they can access your Dropbox account!

The code

Here's the code you need.

import com.dropbox.core.*;
import com.dropbox.core.json.JsonReader;

import java.io.*;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import lejos.hardware.lcd.LCD;

/**
 * An example command-line application that runs through the web-based OAuth
 * flow (using {@link DbxWebAuth}).
 * 
 * By Mark Crosbie http://thinkbricks.net
 * Modified from the Dropbox tutorial code
 */
public class GetAccessToken {
	
	// The access token is saved in this file on the EV3 SDcard
	public static final String accessTokenFilename = "./access-token.json";
	
    public static void main(String[] args) throws IOException {
    	
    	LCD.clear();
    	
    	System.out.println("-- Get Dropbox auth token --");
    	System.out.println("1. Log into Dropbox and go to the App Console in your account");
    	System.out.println("2. Click on the app you created for the EV3");
    	System.out.print("3. Enter the App key value here: ");
        String appKey = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (appKey == null) {
            System.exit(1); return;
        }
        appKey = appKey.trim();
        
        System.out.println("");
        System.out.print("4. Enter the App secret value here: ");
        String appSecret = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (appSecret == null) {
            System.exit(1); return;
        }
        appSecret = appSecret.trim();
        System.out.println("");
        
    	System.out.println("5. Starting Dropbox auth flow");
    	DbxAppInfo appInfo = new DbxAppInfo(appKey, appSecret);

        String userLocale = Locale.getDefault().toString();
        DbxRequestConfig config = new DbxRequestConfig("JavaTutorial/1.0", userLocale);
        DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(config, appInfo);

        // Run through Dropbox API authorization process
        String authorizeUrl = webAuth.start();
        System.out.println("6. Go to " + authorizeUrl);
        System.out.println("7. Click \"Allow\" (you might have to log in first).");
        System.out.println("8. Copy the authorization code.");
        System.out.print("9. Enter the authorization code here: ");

        String code = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (code == null) {
            System.exit(1); return;
        }
        code = code.trim();

        DbxAuthFinish authFinish;
        try {
            authFinish = webAuth.finish(code);
        }
        catch (DbxException ex) {
            System.err.println("Error in DbxWebAuth.start: " + ex.getMessage());
            System.exit(1); return;
        }

        System.out.println("10. Authorization complete.");
        System.out.println("- User ID: " + authFinish.userId);
        System.out.println("- Access Token: " + authFinish.accessToken);

        // Save auth information to output file.
        DbxAuthInfo authInfo = new DbxAuthInfo(authFinish.accessToken, appInfo.host);
        try {
            DbxAuthInfo.Writer.writeToFile(authInfo, accessTokenFilename);
            System.out.println("Saved authorization information to \"" + accessTokenFilename + "\".");
        }
        catch (IOException ex) {
            System.err.println("Error saving to : " + ex.getMessage());
            System.err.println("Dumping to stderr instead:");
            DbxAuthInfo.Writer.writeToStream(authInfo, System.err);
            System.exit(1); return;
        }
    }
}
]]>
http://thinkbricks.net/set-up-dropbox-in-lejos-on-the-ev3/feed/ 1
Book review: Lego Mindstorms EV3 Essentials eBook http://thinkbricks.net/book-review-lego-mindstorms-ev3-essentials-ebook/ http://thinkbricks.net/book-review-lego-mindstorms-ev3-essentials-ebook/#respond Wed, 21 Jan 2015 14:38:20 +0000 http://thinkbricks.net/?p=1176

I received a review electronic copy of Packt Publishing’s ‘Lego Mindstorms EV3 Essentials’ book. This book covers Java and leJOS programming on the EV3, so it differs from most other books on the market in that it choose a 3rd party environment rather than relying on the Lego-supplied one. It also requires a Linux environment as you will be typing a lot of commands in the terminal. The review copy I received is in electronic format so I can’t comment on the final print quality.

The challenge with writing a book based on an evolving open-source program is that you will be forever behind the curve. Despite being a relatively new publication this book is based on the 0.8.1 release of leJOS, which has been superseded by the 0.9.0 release. The leJOS team are constantly improving the platform and making it easier to install and program, so this book has already fallen out-of-date.

Chapter 2 of the ebook opens with coverage of the Lego Mindstorms EV3, and a survey of the sensors, motors and EV3 programmable brick. While it is welcome to have this in the book the content is nothing new; multiple pictures of the major pieces with some descriptive text. You can get this from Lego’s official website, and spending the first 40 pages of the book covering it again was not needed.

In Chapter 3 the on-brick programming functions of the EV3 brick area covered. Now this is where I started to get confused; wasn’t this book meant to be about leJOS programming and more advanced topics? Chapter 3 spends 30 pages covering on-brick programming, before finally we get to…

Chapter 4: leJOS – at last! This chapter introduces the leJOS Java environment for the EV3. Now the first problem is that the instructions given here are very Linux specific, so if you have a Windows or Mac then you are out of luck. Don’t worry though; Windows users have a graphical installer available to them from the official lejos.org website.

Chapter 5 discusses various ways to connect to the EV3. If you have a wifi dongle your EV3 can connect to your wifi hub and then you can simply ssh into it (or better yet, connect via the Eclipse plugin). If you don’t have a wifi dongle then you can use the USB cable and ssh to 10.0.1.1, which is the address the EV3 appears as to your PC or Mac.

This chapter spends a lot of time discussing how to configure the wifi password on the EV3 by editing the /etc/wpa_supplicant.conf file. Now this is certainly the hard-core Linux way to solve this problem, but by far the easier approach is to use the built-in wifi configuration screen on the EV3 to type in your wifi passphrase and connect automatically. This is covered in better detail at the leJOS website.

Chapter 6: this chapter covers programming the EV3 in Java, and it’s where I have a big issues with the book. It leaps into a discussion of the Gradle Java build environment. However all of the guidance on the lejos.org website is around using Eclipse to do your development, with ant build files. There’s no problem in choosing an alternate build environment but I think that an introductory book should have just stuck to the standard IDE suggested by the leJOS project. Another problem in the text is that once you have compiled your program the book suggests that you remove the SDcard from the EV3 and insert it into the computer to manually copy the .class files over. But we just spent the whole last chapter configuring our wifi and setting up ssh keys to avoid this! Very confusing.

Chapter 7 covers the basic operation of moving the motor and using the touch sensor. This is so basic that it really doesn’t require a whole chapter; one program to make the motor go forwards and another to wait for a press of the touch sensor.

Chapter 8, 9 and 10 discuss building a line-follower robot (your read that right; three chapters to cover one of the most basic robots). I was disappointed to find that the code in this chapter re-invented the wheel. It built a very simple differential-drive line follower robot that used simple rotations to try and find the line. The logic of the line-follower program uses a narrow sweep to find the line and if that fails it performs a wider sweep. This is the classic single sensor approach to line-following.

The author spends 60 pages over three chapters creating the line-follower code. This is the longest treatment of a line-follower robot I have ever read. I would suggest instead presenting the final program first and then explaining the parts step-by-step. I found it very difficult to follow all of the modifications made to the source code over three chapters.

Avoiding re-inventing code is critical to bug-free programming, but the sample line-follower robot reinvents the DifferentialPilot class from leJOS. There is little point in choosing the leJOS environment if you are not going to show users how to get the most advantage from using the class library!

The code also failed to perform one of the most basic tasks of a line-following robot; calibrating the colour sensor to the line and non-line parts of the floor! It assumes that you can specify the colour of the line absolutely in the code, and there will be no interference from ambient light or noise. As anyone who has built a line-follower knows this is far from true!

So now we’ve built a basic line-follower robot and…the book is complete! Appendix A explains how to use Make in great detail (why?) and Appendix B gives two pages over to the various IDEs available for Java (again, why?)

This book does not contain building instructions, and it contains one programming project; a very simple line-following robot.

Conclusion: I’d avoid buying this book and instead use the tutorials available for free on the lejos.org website. It was very disappointing, spending more time on introductory concepts instead of creating advanced projects in Java and leJOS.

]]>
http://thinkbricks.net/book-review-lego-mindstorms-ev3-essentials-ebook/feed/ 0
Red Racer – a power functions racing car http://thinkbricks.net/red-racer-a-power-functions-racing-car/ http://thinkbricks.net/red-racer-a-power-functions-racing-car/#respond Sun, 21 Dec 2014 17:53:15 +0000 http://thinkbricks.net/?p=1139

Sometimes it’s fun to just build something different for a change. Red Racer is my version of Sunsky’s lovely Snow White Racing Machine  which I updated to use the new power functions servo for steering and medium motor for drive. I also styled it in red.

I came across the Show White racing machine a few years ago and had saved it for a future date to build. I really liked the clean and simple lines and compact design of the original, and decided to take advantage of the Christmas holiday to build my own version.

My first challenge was that I didn’t have any of the steering parts used in the original racer! Time for some thinking…if I was going to change how the steering worked I may as well upgrade the steering to use the new power functions servo motor.

Luckily Sunsky’s post on the original design had presented detailed disassembly instructions so I was able to build an initial version of the racer, and then modify it to use the new Power Functions motor and servo. I had to widen the chassis by one stud so that everything would fit, and increase the length too so the servo would fit.

The original car was styled in white, but I chose red as I did not have enough white pieces. One thing I learned from this build; I’ve a lot to learn about designing bodies for cars!

2014-12-20 23.39.36 HDR 2014-12-20 23.46.19 HDR 2014-12-20 23.46.08 HDR 2014-12-20 23.45.55 HDR 2014-12-20 23.45.35 HDR 2014-12-20 23.45.17 HDR 2014-12-20 23.45.05 HDR 2014-12-20 23.45.00 HDR 2014-12-20 23.44.43

]]>
http://thinkbricks.net/red-racer-a-power-functions-racing-car/feed/ 0
Review: The Lego Mindstorms EV3 Idea Book http://thinkbricks.net/review-the-lego-mindstorms-ev3-idea-book/ http://thinkbricks.net/review-the-lego-mindstorms-ev3-idea-book/#respond Sat, 13 Dec 2014 23:20:27 +0000 http://thinkbricks.net/?p=1067 EV3-IB_cover-front_newYoshihito Isogawa is well known for his excellent Technic Idea book series, and now he is back with an idea book targeted for the EV3. The ideas are as imaginative as ever, captured in Isogawa-san’s signature style of close-up images. Read on for my review of The Lego Mindstorms EV3 Idea Book from NoStarch Press…

The first thing to note about this book, unlike many other Mindstorms EV3 publications, is that it is not about building robots. In a way this makes Yoshihito’s book unique in that it focuses on techniques you can incorporate into your own creations instead of presenting you with amazing fully realised robots. The book is also not about EV3 programming, in fact most of the designs in the book require nothing more than a motor and an on-off switch!

Who is this book for?

It’s for anyone who wants to move beyond the models in the EV3 Home set and try to build their own robots. You may be frustrated at how complex it is to build using studless Lego beams. Or you may wonder how some of the advanced robots you see on other websites work. Those builders have mastered the art of taking simple building techniques and using them at scale. Once you learn the same basic building techniques you can apply them over and over again in your creations. This book will start you on the road to learning those building techniques.

Contents

So what is in the book? Well you are in for a treat; 181 different builds ranging from simple gear ratios to walking robots using only the parts in the retail Lego Mindstorms EV3 31313 set.

The book is broken into 6 broad topic areas:

  1. Basic mechanisms: gets you up and running with gear ratios, worm drives, changing the angle of rotation, reciprocating mechanisms and other techniques.
  2. Vehicles: now we start to move with various ways of building wheeled and tracked vehicles.
  3. Moving without wheels: ditch the wheel and walk using legs!
  4. Arms, Wing and other Movements: if you want to adorn your robot with droppers, flapping wings or interesting movements this section presents some ideas. I particularly like the ‘lifting things’ section that presents designs for simple forklift and scissor jack lifting mechanisms that could be built into any robot.
  5. Using sensors: this section is specific to the EV3 sensors and shows how to trigger them using different mechanisms. If you ever had the original Constructopedia from the first Mindstorms RIS set then this will bring back memories!
  6. Something extra: this section shows how to join beams at an angle using the Pythagorean theorem, and how to build a stand for an iPad.

Some sample images

These images give you a sense for the quality of the artwork in the book. Each of these models is constructed in multiple steps, but the book does not give traditional Lego step-by-step building instructions. You will need to do a little detective work to figure out how to build each model from the parts in the EV3 kit, but don’t worry, each model is shown from multiple angles and tricky steps are explained clearly.

EV3IB_sample-model_3_largeEV3IB_sample-model_2_largeEV3IB_sample-model_1_largeEV3IB_sample-model_5_large

The production quality of the book is very high. I really like the new wide-format and glossy colours that NoStarch are using for this book, and the previous two books from Sariel.

2014-12-07 10.55.40

Conclusion

This is a must-have book for any aspiring robot-builder to have on their bookshelf. You will find yourself returning to it over and again to look up building techniques. I have only had my copy for a week and it’s already very well thumbed!

]]>
http://thinkbricks.net/review-the-lego-mindstorms-ev3-idea-book/feed/ 0
‘Incredible Lego Technic’ book review http://thinkbricks.net/incredible-lego-technic-book-review/ http://thinkbricks.net/incredible-lego-technic-book-review/#respond Wed, 19 Nov 2014 16:07:46 +0000 http://thinkbricks.net/?p=1023

I was fortunate enough to receive a review copy of Sariel’s latest book titled Incredible Lego Technic and published by NoStarch Press. Unlike Sariel’s previous book this is a compendium of amazing and inspiring Lego Technic models by builders around the world. You won’t find detailed building instructions here, instead each model is presented in stunning colour with a description of the model and some history behind the original design.

One thing I really liked about this book was the lay-flat binding allowed the book to stay open on the desk as I read. This is a book where you can dip in and out and read about models that interest you, or pick a specific model and spend some time studying it. The production values are very high, with the technical advisor Eric Albrecht (aka Blackbird) ensuring that each model is well presented.

2014-11-15 14.33.06

Cover of book

Lay-flat binding makes reading easy

Lay-flat binding makes reading easy

Models

The models are split into sections by theme. There’s something here for everyone, whether you like earth movers or supercars!

  1. Agricultural – tractors and other farm equipment
  2. Aircraft
  3. Automotive
  4. Construction equipment
  5. Miscellaneous
  6. Motorbikes
  7. Supercars
  8. Tracked Vehicles
  9. Trucks
  10. Watercraft

One improvement I would suggest is to include a link to a webpage or Brickshelf gallery for each model so that you can read more once you find something that interests you.

High resolution images

Here are some samples from the book in high-resolution so you can see the details of each model.

[See image gallery at thinkbricks.net]

]]>
http://thinkbricks.net/incredible-lego-technic-book-review/feed/ 0