Adafruit: 8x8 Blue LED Matrix Panel

From eLinux.org
Jump to: navigation, search


Overview

Overview: 2
Wiring:   1, show a picture with your matrix.
Code:     1, Clean it up some more.
git/Compiles with make: 2  make works
Demo:     2
Total:    8  Second grading: Looks better, but grade stays the same.
Comments: Looks good. I wish you would have extended what I did a bit more.

This Mini Project dealt with using Adafruit's 8x8 Blue LED Matrix. The source code they provided is written for Arduino. However, I am using the Beagle Bone instead. Luckily, Dr. Yoder has provided an example program called matrixLEDi2c.c that interfaces the Beagle. You can download or observe his source code here: Dr. Yoder's github repository. I editted this code to retain most of Dr. Yoder's original code, plus I added a design of my own. You can download my updated version from jungeml's github repository.

Inputs and Outputs

The LED Matrix uses an i2c port. Here is the hardware configuration of the Beagle Bone as shown below. Wire up the LED Maxtrix to the Beagle by attaching the Vdd to the 3.3V + bus, the GND to the - bus and SDA to SDA (pin 20) and SCLK to SCL (pin 19). You will also need to attach two pull-up resistors. Get two 4.7KΩ resistors. Attach one between SDA and Vdd. Attach the other between SCL and Vdd.

300px 300px

Software

I changed code in 'matrixLEDi2c.c' file. I also added a header file that stored the helper functions plus the static variables. I added my own design and also turned off the Matrix when the program was finished. As seen below:

Here is the main file

/*
Editted by Michael Junge
my2cset.c - First try at controlling Adafruit 8x8matrix.
Mark A. Yoder, 14-Aug-2012.
Page numbers are from the HT16K33 manual
http://www.adafruit.com/datasheets/ht16K33v110.pdf

i2cset.c - A user-space program to write an I2C register.
Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004-2010 Jean Delvare <khali@linux-fr.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA.
*/

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "i2c-dev.h"
#include "i2cbusses.h"
#include "matrixLEDi2c.h"


int main(int argc, char *argv[])
{
	int res, i2cbus, address, size, file;
	int value, daddress;
	char filename[20];
	int force = 0, readback = 1;
	__u16 block[I2C_SMBUS_BLOCK_MAX];
	int len;

	i2cbus = lookup_i2c_bus("3");
	printf("i2cbus = %d\n", i2cbus);
	if (i2cbus < 0)
		help();

	address = parse_i2c_address("0x70");
	printf("address = 0x%2x\n", address);
	if (address < 0)
		help();

	size = I2C_SMBUS_BYTE;

	daddress = 0x21;
	if (daddress < 0 || daddress > 0xff) {
		fprintf(stderr, "Error: Data address invalid!\n");
		help();
	}

	file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
	printf("file = %d\n", file);
	if (file < 0
		|| check_funcs(file, size)
		|| set_slave_addr(file, address, force))
		exit(1);


	switch (size) {
	case I2C_SMBUS_BYTE:
		daddress = 0x21; // Start oscillator (page 10)
		printf("writing: 0x%02x\n", daddress);
		res = i2c_smbus_write_byte(file, daddress);

		daddress = 0x81; // Display on, blinking off (page 11)
		printf("writing: 0x%02x\n", daddress);
		res = i2c_smbus_write_byte(file, daddress);

		daddress = 0xe7; // Full brightness (page 15)
		printf("writing: 0x%02x\n", daddress);
		res = i2c_smbus_write_byte(file, daddress);

		daddress = 0x00; // Start writing to address 0 (page 13)
		printf("writing: 0x%02x\n", daddress);
		res = i2c_smbus_write_byte(file, daddress);

		int i;

		displayImage(smile_bmp,res, daddress, file);
		displayImage(frown_bmp,res, daddress, file);
		displayImage(neutral_bmp,res, daddress, file);
		displayImage(my_bmp,res, daddress, file);
		sleep(4);
		

		// Closing file and turning off Matrix
		printf("Closing file and turning off the LED Matrix\n");
		daddress = 0x20;		
		//for(daddress = 0xef; daddress >= 0xe0; daddress--) {
		printf("writing: 0x%02x\n", daddress);
		res = i2c_smbus_write_byte(file, daddress);

		usleep(500000); // Sleep 0.5 seconds
		

		break;

	case I2C_SMBUS_WORD_DATA:
		res = i2c_smbus_write_word_data(file, daddress, value);
		break;
	case I2C_SMBUS_BLOCK_DATA:
		res = i2c_smbus_write_block_data(file, daddress, len, (const __u8 *)block);
		break;
	case I2C_SMBUS_I2C_BLOCK_DATA:
		res = i2c_smbus_write_i2c_block_data(file, daddress, len, (const __u8 *)block);
		break;
	default: /* I2C_SMBUS_BYTE_DATA */
		res = i2c_smbus_write_byte_data(file, daddress, value);
		break;
	}
	if (res < 0) {
		fprintf(stderr, "Error: Write failed\n");
		close(file);
		exit(1);
		}

	if (!readback) { /* We're done */
		close(file);
		exit(0);
		}

	switch (size) {
		case I2C_SMBUS_BYTE:
			res = i2c_smbus_read_byte(file);
			value = daddress;
			break;
		case I2C_SMBUS_WORD_DATA:
			res = i2c_smbus_read_word_data(file, daddress);
			break;
		default: /* I2C_SMBUS_BYTE_DATA */
			res = i2c_smbus_read_byte_data(file, daddress);
			}
	close(file);

	exit(0);
}

Here is the header file

//Header file for matrixLEDi2c
//created by Michael Junge



__u16 block[I2C_SMBUS_BLOCK_MAX];


static __u16 smile_bmp[] = {0x3C, 0x42, 0x95, 0xA1, 0xA1, 0x95, 0x42, 0x3C};
static __u16 frown_bmp[]=  {0x3C, 0x42, 0xA5, 0x91, 0x91, 0xA5, 0x42, 0x3C};
static __u16 neutral_bmp[]={0x3C, 0x42, 0x95, 0x91, 0x91, 0x95, 0x42, 0x3C};
static __u16 my_bmp[] =    {0xA5, 0x42, 0xA5, 0xA5, 0xA5, 0xA5, 0x42, 0xA5};

static void help(void) __attribute__ ((noreturn));




int displayImage(__u16 bmp[], int res, int daddress, int file)
{
	int i;
	for(i=0; i<8; i++)
        {
	     block[i] = (bmp[i]&0xfe) >>1 |
             (bmp[i]&0x01) << 7;
        }
        res = i2c_smbus_write_i2c_block_data(file, daddress, 16,
        	(__u8 *)block);
        sleep(1);

}


static void help(void)
{
	fprintf(stderr, "Usage: my2cset (hardwired to bus 3, address 0x70)\n");
	exit(1);
}

static int check_funcs(int file, int size)
{
	unsigned long funcs;

	/* check adapter functionality */
	if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
		fprintf(stderr, "Error: Could not get the adapter "
		"functionality matrix: %s\n", strerror(errno));
		return -1;
	}

	switch (size) {
	case I2C_SMBUS_BYTE:
		if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
			fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
			return -1;
		}
		break;

	case I2C_SMBUS_BYTE_DATA:
		if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
			fprintf(stderr, MISSING_FUNC_FMT, "SMBus write byte");
			return -1;
		}
		break;

	case I2C_SMBUS_WORD_DATA:
		if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) {
			fprintf(stderr, MISSING_FUNC_FMT, "SMBus write word");
			return -1;
		}
		break;

	case I2C_SMBUS_BLOCK_DATA:
		if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) {
			fprintf(stderr, MISSING_FUNC_FMT, "SMBus block write");
			return -1;
		}
		break;
	case I2C_SMBUS_I2C_BLOCK_DATA:
		if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
			fprintf(stderr, MISSING_FUNC_FMT, "I2C block write");
			return -1;
		}
		break;
	}

	return 0;
}

This code example and the required resources can be found in jungeml's github repository