arduino教程系列39-Arduino+Colordunio RGB 详细讲解与演示实验
Randy 于 2012-5-28 16:09 编辑
话说此次实验说用到的Colordunio RGB是一个专门为RGB全彩点阵设计的一个Arduino 控制板模块,此模块除了能独立给RGB点阵驱动外,也是可以当作一个Arduino的控制板来使用的哦。非常的方便和实用,板载的芯片是ATmega 328的芯片,板子上面也引出了ISP接口,可以随时给328芯片烧写bootloader。目前看到的缺点是不想其他Arduino Uno 板子一样,没有引出了相应的I/0口出来,只是引出了一些IIC接口和供电接口。后续有时间会开发一个带I/0口的板子,使购买者买了这个板子就不需要买多一块Uno板子或者是MEGA 2560啥的板子了。希望大家多多支持我们!谢谢!
需要讲解这个Colordunio ,必须分两个步骤来讲。
第一, 是讲解RGB点阵的使用与工作原理。
先来看一下我们使用所需要的RGB点阵:
2012-5-28 15:37 上传
(77.26 KB)
RGB简单的说,就是R、G、B(红、绿、蓝)三种颜色的英文缩写。一开始没接触过点阵的朋友,这个最好先从单色的8X8点阵开始学习,驱动原理几乎一样的。只不过,RGB多了两种需要显示的颜色,所以会相对于比较麻烦一点。所以现在我们简单的描述一下单色的点阵的工作原理:
2012-5-28 15:37 上传
(51.21 KB)
图(1)8×8点阵LED外观及引脚图
2012-5-28 15:37 上传
(36.07 KB)
图(2)8×8点阵LED等效电路
汉字显示屏用于显示汉字、字符及图像信息,在公共汽车、银行、医院及户外广告等地方都有广泛的应用。下面是简单的汉字显示屏的制作,由单片机控制汉字的显示内容。为了降低成本,使用了四块8×8的LED点阵发光管的模块,组成了一个16×16的LED点阵显示屏,如图(3)所示。在这里仅做了二十五个汉字的显示,在实际的使用中可以根据这个原理自行的扩展显示的汉字,下面是介绍汉字显示的原理。
LED驱动显示采用动态扫描方法,动态扫描方式是逐行轮流点亮,这样扫描驱动电路就可以实现多行的同名列共用一套列驱动器。以16×16点阵为例,把所有同一行的发光管的阴极连在一起,把所有同一列的发光管的阳极连在一起(共阴的接法),先送出对应第1列发光管亮灭的数据并锁存,然后选通第1列使其燃亮一定的时间,然后熄灭;再送出第2列的数据并锁存,然后选通第2列使其燃亮相同的时间,然后熄灭;….第16列之后,又重新燃亮第1列,反复轮回。当这样轮回的速度足够快(每秒24次以上),由于人眼的视觉暂留现象,就能看到显示屏上稳定的图形。该方法能驱动较多的LED,控制方式较灵活,而且节省单片机的资源。
显示数据可通过单片机的P0,,P2口接驱动电路传输到点阵行引脚。
LED点阵显示模块进行的方法有两种:
1)水平方向(X方向)扫描,即逐列扫描的方式(简称列扫描方式):此时用一个P口输出列码决定哪一列能亮(相当于位码),用另一个P口输出行码(列数据),决定该列上哪个LED亮(相当于段码)。能亮的列从左到右扫描完16列(相当于位码循环移动16次)即显示出一个完整的图像。
(2)竖直方向(Y方向)扫描,即逐行扫描方式(简称行扫描方式):此时用一个P口输出决定哪一行能亮(相当于位码),另一个P口输出列码(行数据,行数据为将列数据的点阵旋转90度的数据)决定该行上哪些LED灯亮(相当于段码)。能亮的行从上向下扫描完16行(相当于位码循环移位16次)即显示一帧完整的图像。
本设计应用的是第一种的扫描方法,即水平方向(X方向)扫描。
每一个字由16行16列的点阵形成显示,即每个字均由256个点阵来表示,我们可以把每一个点理解为一个像素。一般我们使用的16×16的点阵宋体字库,即所谓的16×16,是每一个汉字在纵横各16点的区域内显示的。汉字库从该位置起的32字节信息记录了该字的
字模信息。事实上这个汉字屏不仅可以显示汉字,也可以显示在256像素范围内的任何图形。
我们以水平方向(x方向)扫描显示汉字的“杨”为例来说明其扫描原理,每一个字由16行16列的点阵组成显示,如图下的,如果用8位的AT89S51的单片机来控制,由于单片机的总线为8位,一个字需要拆分成两个部分。一般我们把它分解成上部分和下部分,上部分由816的点阵组成,下部分也由816的点阵组成。在本例中单片机首先显示的是左上角的第一列的部分,即第0列的P00~P07口。方向为P07到P00,显示汉字“杨”的时候,P00到P02都是灭的,P03亮,因为行接阴极,即二进制11110111,转换为16进制为F7H,如图(4)所示。
上半部分第一列完成之后,继续扫描下半部分的第一列,即从P27向P20方向扫描,从上图可以看到,这一列P2.2亮,其余全部灭,所以代码为11111011,16进制为FBH,然后单片机转向上半部的第二列,除了P03亮,其他的都不亮,即为11110111,16进制为F7H,这一列扫描完成之后继续进行下半部分的扫描,除了P20\P21亮,其他的为不亮,为二进制11111100,即16进制FCH。
按照这个方法,继续进行下面的扫描,一共扫描32个8位,可以得出汉字“杨”的扫描代码为 : F7H FBH F7H FCH 37H FFH 00H 00H
B7H FFH 77H FEH F5H F7H BDH DBH;
9DH ECH 2DH F7H B5H F9H 39H BEH
BDH 7FH 3FH 80H FFH FFH FFH FFH;
2012-5-28 15:37 上传
(43.17 KB)
2012-5-28 15:37 上传
(42.4 KB)
(4)显示原理图
由这个原理可以看到,无论显示何种字体或图像,都可以用这种方法来分析出它的扫描代码从而显示在屏幕上。了解汉字的显示原理之后,那如何得到汉字的字模信息呢?现在有一些现成的汉字字模生成软件,可从网上下载汉字字库提取程序直接提取字库,如图(5)所示的为一种字模生成软件,软件打开后输入汉字,点击“检取”后,十六进制数据汉字代码即可以自动生成,把我们需要的竖排数据复制到我们的程序即可。
单色的点阵驱动就是以上的工作原理来驱动显示数字或者中文的了,双色的点阵甚至RGB LED点阵工作原理也是如此。
第二, 讲解的是驱动本实验RGB点阵的主板——Colordunio V2.0
先给大家上一个图片看看:
2012-5-28 15:37 上传
(93.17 KB)
看上图,我们可以看得出两边引出的两排RGB插座,是预留给RGB专用的插槽。使用时直接将RGB往上面插上去即可,简单,方便,使用!
板子的旁边也引出了一些与USB转TTL进行通讯的接口。这样我们需要给板子更新新的程序直接把USB转TTL模块;连接上就可以进行在线实时更新需要更新的程序了。这样省去了很多下载程序是不必要的麻烦。
现在来说一下重点,就是Arduino 控制RGB点阵的过程。
看一下我们的线路连接定义:
2012-5-28 15:54 上传
(19.54 KB)
以上是硬件连接的描述。
下面可以看一下硬件实物连接的样子。
2012-5-28 15:37 上传
(67.17 KB)
很方便的连接,如果没有专门配对的FT232RT模块,可以用杜邦线进行连接也是可以的哦!端口定义是一样的。
硬件连接完毕以后,就是需要进行软件的程序下载了。软件版本可以选择各种版本,我们所使用的是Arduino IDE 0023或者Arduino IDE 1.0 版本的!
测试代码是一下代码:
/*
ColorduinoPlasma - Plasma demo using Colorduino Library for Arduino
此函数的功能是,让RGB模块显示出渐变的R、G、B的组合颜色。
效果是和我们在街上看到的那个RGB全彩显示屏显示的是一样的,只不过是我们现在只做的是8X8的点阵。可以通过74HC595进行扩展达到更大的显示效果!
*/
#include <Colorduino.h>
typedef struct //重新进行数据类型定义
{
unsigned char r;
unsigned char g;
unsigned char b;
} ColorRGB;
//a color with 3 components: h, s and v 一个颜色由H ,S ,V三个部分组成
typedef struct
{
unsigned char h;
unsigned char s;
unsigned char v;
} ColorHSV;
unsigned char plasma[ColorduinoScreenWidth][ColorduinoScreenHeight]; //定义Colorduino Screen 的宽度和高度
long paletteShift;
//Converts an HSV color to RGB color —HSV颜色转换为RGB颜色
void HSVtoRGB(void *vRGB, void *vHSV)
{
float r, g, b, h, s, v; //这个函数的工作方式的类型是浮点型0和1
float f, p, q, t;
int i;
ColorRGB *colorRGB=(ColorRGB *)vRGB; //两个RGB颜色相与的公式
ColorHSV *colorHSV=(ColorHSV *)vHSV;
h = (float)(colorHSV->h / 256.0);
s = (float)(colorHSV->s / 256.0);
v = (float)(colorHSV->v / 256.0);
//如果饱和度为0,那这个颜色就是为白的颜色,也可以看得出是HSV和RGB的值是相等的!
if(s == 0.0) {
b = v;
g = b;
r = g;
}
//如果这个饱和度大于0,那就需要更复杂的计算
else
{
h *= 6.0; //h=h*6.0把颜色调到0和6之间,这样就会比较好计算!
i = (int)(floor(h)); //例如2.7变成2、3.01变成3或者4.9999变成4
f = h - i;//the fractional part of h — h为小数部分
p = (float)(v * (1.0 - s));
q = (float)(v * (1.0 - (s * f)));
t = (float)(v * (1.0 - (s * (1.0 - f))));
switch(i) //利用Switch进行判断
{
case 0: r=v; g=t; b=p; break;
case 1: r=q; g=v; b=p; break;
case 2: r=p; g=v; b=t; break;
case 3: r=p; g=q; b=v; break;
case 4: r=t; g=p; b=v; break;
case 5: r=v; g=p; b=q; break;
default: r = g = b = 0; break;
}
}
colorRGB->r = (int)(r * 255.0);//得出RGB中R的数值
colorRGB->g = (int)(g * 255.0);//得出RGB中G的数值
colorRGB->b = (int)(b * 255.0);//得出RGB中B的数值
}
float dist(float a, float b, float c, float d)
{
return sqrt((c-a)*(c-a)+(d-b)*(d-b));//开平方根
}
void plasma_morph()
{
unsigned char x,y;
float value;
ColorRGB colorRGB;
ColorHSV colorHSV;
for(y = 0; y < ColorduinoScreenHeight; y++)
for(x = 0; x < ColorduinoScreenWidth; x++) {
{
value = sin(dist(x + paletteShift, y, 128.0, 128.0) / 8.0)
+ sin(dist(x, y, 64.0, 64.0) / 8.0)
+ sin(dist(x, y + paletteShift / 7, 192.0, 64) / 7.0)
+ sin(dist(x, y, 192.0, 100.0) / 8.0);
colorHSV.h=(unsigned char)((value) * 128)&0xff;
colorHSV.s=255;
colorHSV.v=255;
HSVtoRGB(&colorRGB, &colorHSV);
Colorduino.SetPixel(x, y, colorRGB.r, colorRGB.g, colorRGB.b);
}
}
paletteShift++;
Colorduino.FlipPage(); // 屏幕显示它交换缓冲区
}
/********************************************************
作者: ColorFill
功能: 填充整个画面颜色
参数: R: the value of RED. Range:RED 0~255
G: the value of GREEN. Range:RED 0~255
B: the value of BLUE. Range:RED 0~255
********************************************************/
void ColorFill(unsigned char R,unsigned char G,unsigned char B)
{
PixelRGB *p = Colorduino.GetPixel(0,0);
for (unsigned char y=0;y<ColorduinoScreenWidth;y++) {
for(unsigned char x=0;x<ColorduinoScreenHeight;x++) {
p->r = R;
p->g = G;
p->b = B;
p++;
}
}
Colorduino.FlipPage();
}
void setup() //此函数是进行初始化的操作
{
Colorduino.Init(); // 初始化Colorduino
// compensate for relative intensity differences in R/G/B brightness
// array of 6-bit base values for RGB (0~63)
// whiteBalVal[0]=red
// whiteBalVal[1]=green
// whiteBalVal[2]=blue
unsigned char whiteBalVal[3] = {36,63,63}; // for LEDSEE 6x6cm round matrix
Colorduino.SetWhiteBal(whiteBalVal);
// start with morphing plasma, but allow going to color cycling if desired.
paletteShift=128000;
unsigned char bcolor;
//generate the plasma once
for(unsigned char y = 0; y < ColorduinoScreenHeight; y++)
for(unsigned char x = 0; x < ColorduinoScreenWidth; x++)
{
//the plasma buffer is a sum of sines
bcolor = (unsigned char)
(
128.0 + (128.0 * sin(x*8.0 / 16.0))
+ 128.0 + (128.0 * sin(y*8.0 / 16.0))
) / 2;
plasma[x][y] = bcolor;
}
// 调整白平衡的话,你可以取消这一行!
// 在loop()函数中注释掉plasma_morph()
// 用在whiteBalVal上面做实验
// ColorFill(255,255,255);
}
void loop() //执行部分,相当于执行了plasma_morph()函数即可
{
plasma_morph();
}
我们实验中得出的结果!
2012-5-28 15:53 上传
(99.53 KB)
2012-5-28 15:54 上传
(128.85 KB)
有什么问题欢迎提问,大家一起学习,开源硬件,资料来自网络,分享整理快乐!
via - 极客工坊