Comments: Transparent Graphical OLED Breakout Hookup Guide

Pages

Comments 3 comments

  • Can somebody give some advice, how i could use the display with an Raspberry Pi 3 B+ ?

    • Well, I was just thinking about this and here's my first reaction.... On the B+ you don't have any convenient way to run C++ or Arduino code (right? I haven't really pushed the limits here). So unfortunately you won't be able to use HyperDisplay directly. IMO that leaves you with two options: 1. try reading the code for the driver to understand what I2C commands are used to set it up and draw pixels, then making that happen on the Pi with Python, or 2. Control the graphical OLED with an arduino-compatible microcontroller that runs HyperDisplay, and use a communication protocol of your own to activate the various drawing functions from the Pi. This is a pretty good option for the Transparent Graphical OLED since it is on/off only - you won't need to worry about handling colors in your protocol.

      Let us know what you end up doing, it could be a good resource for others!

  • I saw the JPEG to code script and was intrigued. I haven't been able to test it, and it could use a bit of polish, but here is an improved (?) version. The main addition is the ability to handle color images and to scale them; unverified. Here is the Python source: #!/usr/bin/env python3 # -- coding: utf-8 --

    """Convert a JPEG image into a format that can be used by the SparkFun HyperDisplay Transparent Graphical OLED Library.
    
    This code relies on the Pillow module. To get it try $ pip3 install Pillow
    
    Exports:
    * process_image(jpg_file_name, size): Process the JPEG file and return an intermediate format.
    * write_function_to_file(pixel_data, size, file_to_write): Write some C/C++ code to a file.
    """
    import getopt
    import sys
    
    from PIL import Image
    
    __author__ = 'Brent Wilkins'
    __version__ = '0.1.0'
    __license__ = 'Open. Not wasting time looking that up.'
    
    
    def _main(argv):
        """Convert the given input JPEG into the desired output format."""
        input_jpg, output_file, size = _parse_args(argv)
        pixel_states = process_image(input_jpg, size)
        write_function_to_file(pixel_states, size, output_file)
    
    
    def _parse_args(argv):
        """Parse the command ine arguments if any were provided.
    
        Return tuple of input JPG file name (str), output file name (str), and a tuple of hopefully ints specifiying
        the desired output size. Warn and exit if two file names and dimensions weren't provided.
        """
        input_file = None
        output_file = None
        width = None
        height = None
    
        try:
            opts, args = getopt.getopt(argv, 'hi:o:w:t:', ['ifile=', 'ofile=', 'width=', 'height='])
        except getopt.GetoptError:
            _fail(2)  # Didn't have the time to find the best exit status, so magic!
        for opt, arg in opts:
            if opt == '-h':
                _fail()
            elif opt in ('-i', '--ifile'):
                input_file = arg
            elif opt in ('-o', '--ofile'):
                output_file = arg
            elif opt in ('-w', '--width'):
                width = arg
            elif opt in ('-t', '--height'):
                height = arg
    
        if input_file and output_file and width and height:
            try:
                width = int(width)
            except ValueError as err:
                print(f'Invalid value given for width. Only interger values are valid: {err}')
                sys.exit(3)  # 3 is pure magic.
            try:
                height = int(height)
            except ValueError as err:
                print(f'Invalid value given for height. Only interger values are valid: {err}')
                sys.exit(3)  # 3 is pure magic.
            size = width, height
    
            print(f'Input file is "{input_file}"')
            print(f'Output file is "{output_file}"')
            print(f'Output dimensions are specified as {size}')
    
            return input_file, output_file, size
        else:
            _fail(2)
    
    
    def process_image(jpg_file_name, size, threshold=127):
        """Process the JPEG file and return an intermediate format.
    
        Params:
            jpg_file_name (str): Name of the image to open for processing.
            size (tuple): The (width, height) of the desired output.
            threshold (int): Pixels with luminance values greater or equal to this will be set high.
    
        Returns:
            List of pixel states. True means the pixel is on, False means it's off.
        """
        pixels = None
        with Image.open(jpg_file_name) as image:
            print(image)
            try:
                image = image.resize(size)
                print(image)
            except TypeError as err:
                print(f"Couldn't resize image: {err}")
                sys.exit(3)  # Again, 3 is pure magic.
            pixels = list(image.getdata())
            image.close()
        # Calculate luminance based on Photometric/digital ITU BT.709. This is likely overkill, but interesting.
        luma = [0.2126*pixel[0] + 0.7152*pixel[1] + 0.0722*pixel[2] for pixel in pixels]
    
        # This produces a result opposite of the script this is based on. Here bright pixels are on.
        return list(map(lambda lum: True if lum >= threshold else False, luma))
    
    
    def _fail(status=0):
        """Print usage and exit the script."""
        print('Usage: jpg_to_pixels.py -i <inputfile> -o <outputfile> -w <width in pixels> -t <height in pixels>')
        sys.exit(status)
    
    
    def write_function_to_file(pixel_data, size, file_to_write):
        """Write some C/C++ code to a file."""
        with open(file_to_write, 'w') as fp:
            # Write the 'header'.
            fp.write('void ShowLogo(void) {\n  myTOLED.clearDisplay();\n\n')
            # Write the array of values.
            width, height = size
            fp.write(f'  const int width = {width};\n  const int height = {height};\n\n')
            str_list = ['  bool states[width*height] = {']
            for idx, state in enumerate(pixel_data):
                val = 'true, ' if state else 'false, '
                if idx == width*height - 1:  # Replace comma on last entry with closing '}'.
                    val = val[:-2]
                    val += '};\n'
                elif (not idx % 8) and (idx != 0):  # Limit the length of generated lines.
                    val += '\n' + 31*' '  # Need 31 spaces for alignment.
                str_list.append(val)
            fp.write(''.join(str_list))
            # Write the loop.
            fp.write('  for ( int i = 0; i < width*height; ++i ) {\n    if (states[i]) {\n      '
                     'myTOLED.pixelSet(i%width, (int)(i/width));\n    }\n  }\n}')
    
    
    if __name__ == '__main__':
        if len(sys.argv) > 1:
            _main(sys.argv[1:])
        else:
            _fail(2)
    

    Here is the output for ./jpg_to_pixels.py -i sflogo.jpg -o out.c -w 12 -t 6 A next step might be to use bits rather than an array of bools to save space.

    void ShowLogo(void) {
      myTOLED.clearDisplay();
    
      const int width = 12;
      const int height = 6;
    
      bool states[width*height] = {true, true, true, true, true, true, true, true, true, 
                                   true, true, true, true, true, true, true, true, 
                                   true, true, false, false, true, true, true, true, 
                                   true, true, true, true, true, true, true, true, 
                                   true, true, true, false, true, false, true, false, 
                                   false, false, true, false, true, false, false, false, 
                                   false, true, false, false, false, false, true, true, 
                                   true, false, false, true, true, true, true, true, 
                                   true, true, true, true, true, true, true};
      for ( int i = 0; i < width*height; ++i ) {
        if (states[i]) {
          myTOLED.pixelSet(i%width, (int)(i/width));
        }
      }
    }
    


If you've found a bug or have other constructive feedback for our tutorial authors, please send us your feedback!