Difference between revisions of "Adafruit: 8x8 Blue LED Matrix Panel"

From eLinux.org
Jump to: navigation, search
(Software)
m
 
(6 intermediate revisions by 2 users not shown)
Line 3: Line 3:
  
 
== Overview ==
 
== Overview ==
 +
<pre style="color:red">
 +
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.
 +
</pre>
  
 
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: [https://github.com/MarkAYoder/BeagleBoard-exercises/tree/master/i2c 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 [https://github.com/jungeml/MiniProject02 jungeml's github repository].
 
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: [https://github.com/MarkAYoder/BeagleBoard-exercises/tree/master/i2c 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 [https://github.com/jungeml/MiniProject02 jungeml's github repository].
Line 8: Line 17:
 
== Inputs and Outputs ==
 
== 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 Maxtri 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&Omega; resistors.  Attach one between SDA and Vdd.  Attach the other between SCL and Vdd.  
+
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&Omega; resistors.  Attach one between SDA and Vdd.  Attach the other between SCL and Vdd.  
 
 
[[File:Bone gpio.JPG|300px]]
 
[[File:BoneGPIO.png|300px]]
 
  
 +
[[File:Matrix Hardware.JPG|300px]]
 +
[[File:Matrix LED XX.JPG|300px]]
  
 
== Software ==  
 
== Software ==  
  
I only changed code in 'matrixLEDi2c.c' file. I added my own design and also turned off the Matrix when the program was finished. As seen below:
+
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
 
<pre>
 
<pre>
 
/*
 
/*
 +
Editted by Michael Junge
 
my2cset.c - First try at controlling Adafruit 8x8matrix.
 
my2cset.c - First try at controlling Adafruit 8x8matrix.
 
Mark A. Yoder, 14-Aug-2012.
 
Mark A. Yoder, 14-Aug-2012.
Line 53: Line 63:
 
#include "i2c-dev.h"
 
#include "i2c-dev.h"
 
#include "i2cbusses.h"
 
#include "i2cbusses.h"
 +
#include "matrixLEDi2c.h"
  
static void help(void) __attribute__ ((noreturn));
 
 
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;
 
}
 
  
 
int main(int argc, char *argv[])
 
int main(int argc, char *argv[])
Line 166: Line 120:
  
 
int i;
 
int i;
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};
 
 
/*
 
* For some reason the display is rotated one column, so pre-unrotate the
 
* data.
 
*/
 
for(i=0; i<8; i++) {
 
block[i] = (smile_bmp[i]&0xfe) >>1 |
 
(smile_bmp[i]&0x01) << 7;
 
}
 
res = i2c_smbus_write_i2c_block_data(file, daddress, 16,
 
(__u8 *)block);
 
 
sleep(2);
 
 
// Display a new picture
 
for(i=0; i<8; i++) {
 
block[i] = (frown_bmp[i]&0xfe) >>1 |
 
(frown_bmp[i]&0x01) << 7;
 
}
 
daddress = 0x00;
 
printf("writing: 0x%02x\n", daddress);
 
res = i2c_smbus_write_byte(file, daddress);
 
 
res = i2c_smbus_write_i2c_block_data(file, daddress, 16,
 
(__u8 *)block);
 
 
sleep(1);
 
 
// Display yet another picture
 
for(i=0; i<8; i++) {
 
block[i] = (neutral_bmp[i]&0xfe) >>1 |
 
(neutral_bmp[i]&0x01) << 7;
 
}
 
daddress = 0x00;
 
printf("writing: 0x%02x\n", daddress);
 
res = i2c_smbus_write_byte(file, daddress);
 
 
res = i2c_smbus_write_i2c_block_data(file, daddress, 16,
 
(__u8 *)block);
 
sleep(1);
 
 
// Display my picture
 
for(i=0; i<8; i++) {
 
block[i] = (my_bmp[i]&0xfe) >>1 |
 
(my_bmp[i]&0x01) << 7;
 
}
 
daddress = 0x00;
 
printf("writing: 0x%02x\n", daddress);
 
res = i2c_smbus_write_byte(file, daddress);
 
  
res = i2c_smbus_write_i2c_block_data(file, daddress, 16,
+
displayImage(smile_bmp,res, daddress, file);
(__u8 *)block);
+
displayImage(frown_bmp,res, daddress, file);
sleep(5);
+
displayImage(neutral_bmp,res, daddress, file);
 +
displayImage(my_bmp,res, daddress, file);
 +
sleep(4);
 +
  
 
// Closing file and turning off Matrix
 
// Closing file and turning off Matrix
Line 232: Line 136:
  
 
usleep(500000); // Sleep 0.5 seconds
 
usleep(500000); // Sleep 0.5 seconds
//}
+
  
 
break;
 
break;
Line 273: Line 177:
 
close(file);
 
close(file);
  
/*if (res < 0) {
+
exit(0);
printf("Warning - readback failed\n");
+
}
} else
+
</pre>
if (res != value) {
+
 
printf("Warning - data mismatch - wrote "
+
Here is the header file
"0x%0*x, read back 0x%0*x\n",
+
<pre>
size == I2C_SMBUS_WORD_DATA ? 4 : 2, value,
+
//Header file for matrixLEDi2c
size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
+
//created by Michael Junge
} else {
+
 
printf("Value 0x%0*x written, readback matched\n",
+
 
size == I2C_SMBUS_WORD_DATA ? 4 : 2, value);
+
 
 +
__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;
 
}
 
}
*/
 
  
exit(0);
+
return 0;
 
}
 
}
 +
 
</pre>
 
</pre>
 
This code example and the required resources can be found in [https://github.com/jungeml/MiniProject02 jungeml's github repository]
 
This code example and the required resources can be found in [https://github.com/jungeml/MiniProject02 jungeml's github repository]

Latest revision as of 11:34, 14 November 2012


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