Lego Mindstorms EV3 with an image with 4 different shades of gray

As mentioned in the previous post, any EV3 is capable of displaying 4 different shades of gray. However, this functionality is not available in the standard Lego programming environment.

When using EV3DEV in combination with C++, there are no libraries available (or I can’t find them 😉 ) to upload easily an image to the LCD screen. You need to write the right values to a screen buffer in order to display an image. But if you do it right, you can get an image like this on the EV3:

A standard Lego Mindstorms EV3 can display four different shades of gray (click on the picture for a short video)

I wrote a simple C# program that scans the complete image, pixel by pixel from left to right and from top to bottom. The image pixel values are converted into a array with the EV3 pixel values.

  ..

  const int MaxDisplayX = 178;
  const int MaxDisplayY = 128;

  Bitmap myBitmap = new Bitmap("Example picture.png");
  Color pixelColor;

  // Start of the array initialization
  System.Console.WriteLine("unsigned short int imageArray[] = {" + Environment.NewLine);

  // Get the color of a pixel within myBitmap.
  for (int y = 0; y < MaxDisplayY; y++)
  {
    for (int x = 0; x < MaxDisplayX; x++)
    {
      pixelColor = myBitmap.GetPixel(x, y);

      // RGB values are always the same, so doesn't matter if I read R, G or B
      switch (pixelColor.R)
      {
        case 0: // Black
          System.Console.Write("0x0000");
          break;
        case 85: // Dark Gray
          System.Console.Write("0x4949");
          break;
        case 170: // Light Gray
          System.Console.Write("0x9292");
          break;
        case 255: // White
          System.Console.Write("0xFFFF");
          break; 
        default:
          break;
      }

      // No ; at the end of the last array element
      if (!((x == (MaxDisplayX - 1)) && (y == (MaxDisplayY - 1))))
      {
        System.Console.Write(", ");
      }
    }
    System.Console.WriteLine(Environment.NewLine);
  }

  // End of the array initialization
  System.Console.WriteLine("};" + Environment.NewLine);
}

Note: the C# program can only convert 4 different values to the pixel array, so the input should be an image that has already been converted into a 4 grayscale image. The image should also have the exact size of the screen, i.e. 178 x 128 pixels. I have only tested it on one grayscale image, so I don’t know if the four grayscale values (0, 85, 170, 255) are always the same four.

The output of the C# program looks like this …

unsigned short int imageArray[] = {

  0x4949, 0x4949, 0x4949, 0x4949, 0x4949, ... etc
  ...
  ...

};

… and is written to the file “imagearray.h”. That file used in the C++ program that runs on the EV3:

..
..
#include "imagearray.h"
..
..
{
  int fbfd = 0;
  char* fbp = 0;

  long int screensize = 0;
  struct fb_var_screeninfo vinfo;
  struct fb_fix_screeninfo finfo;

  fbfd = open("/dev/fb0", O_RDWR);
  if (fbfd == -1)
  {
    exit(-1);  
  }

  if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
  {
    exit(-1);
  }

  /* Get variable screen information */
  if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
  {
    exit(-1);
  }

  /* Figure out the size of the screen in bytes */
  screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

  fbp = (char*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
  if ((int)fbp == -1)
  {
    exit(-1);
  }

  // Iterate over the number of array elements
  // Note: sizeof gives the total number of bytes, therefore we
  //       have to divide by the size of one array element
  for (int i = 0; i < sizeof(imageArray) / sizeof(imageArray[0]); i++)
  {
    // one pixel = 4 bytes in the screen buffer 
    *((unsigned short int*)(fbp + i * 4)) = imageArray[i];
  }
  munmap(fbp, screensize);

  ..
  ..

That’s all. Simple as that.

 

Impression of our visit to Lego World 2017 in Utrecht

From Tuesday October 18 until Saturday October 21, our layout was present at Lego World 2017 in Utrecht, the Netherlands.

Photos of our layout can be viewed on Flickr, please click on the photo below to be teletransported to Flickr.

 

And on Youtube you will find two video impressions:

 

If you like our layout, please like our videos.

Enjoy, Sioux.NET on Track

How to? Synchronizing two threads

In the EV3 programming environment, it is possible to start multiple threads. For example, you want two motors to run simultaneously and when both motors are finished, you want to play a sound. But there is no default mechanism in the programming environment to continue with the main thread when the second has also finished. In  the example below, the “Ready” sound is played too early if motor A finishes before motor B is finished.

Continue reading “How to? Synchronizing two threads”

Loading the train with the 6-axis DOF robot arm

I wrote a small test program for the robot arm to load the train with two containers. Loading the two wagons was done in one minute, so much faster than the candy crane.

Have a look at the video and please share with me what you think of it.