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点阵:

6(1).jpg

2012-5-28 15:37 上传
(77.26 KB)



RGB简单的说,就是R、G、B(红、绿、蓝)三种颜色的英文缩写。一开始没接触过点阵的朋友,这个最好先从单色的8X8点阵开始学习,驱动原理几乎一样的。只不过,RGB多了两种需要显示的颜色,所以会相对于比较麻烦一点。所以现在我们简单的描述一下单色的点阵的工作原理:

7(1).jpg

2012-5-28 15:37 上传
(51.21 KB)

图(1)8×8点阵LED外观及引脚图

8(1).jpg

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;

4.jpg

2012-5-28 15:37 上传
(43.17 KB)

5(1).jpg

2012-5-28 15:37 上传
(42.4 KB)



(4)显示原理图

由这个原理可以看到,无论显示何种字体或图像,都可以用这种方法来分析出它的扫描代码从而显示在屏幕上。了解汉字的显示原理之后,那如何得到汉字的字模信息呢?现在有一些现成的汉字字模生成软件,可从网上下载汉字字库提取程序直接提取字库,如图(5)所示的为一种字模生成软件,软件打开后输入汉字,点击“检取”后,十六进制数据汉字代码即可以自动生成,把我们需要的竖排数据复制到我们的程序即可。





单色的点阵驱动就是以上的工作原理来驱动显示数字或者中文的了,双色的点阵甚至RGB LED点阵工作原理也是如此。



第二, 讲解的是驱动本实验RGB点阵的主板——Colordunio V2.0

先给大家上一个图片看看:

9(1).jpg

2012-5-28 15:37 上传
(93.17 KB)



看上图,我们可以看得出两边引出的两排RGB插座,是预留给RGB专用的插槽。使用时直接将RGB往上面插上去即可,简单,方便,使用!



板子的旁边也引出了一些与USB转TTL进行通讯的接口。这样我们需要给板子更新新的程序直接把USB转TTL模块;连接上就可以进行在线实时更新需要更新的程序了。这样省去了很多下载程序是不必要的麻烦。

现在来说一下重点,就是Arduino 控制RGB点阵的过程。

看一下我们的线路连接定义:

56.jpg

2012-5-28 15:54 上传
(19.54 KB)



以上是硬件连接的描述。

下面可以看一下硬件实物连接的样子。

10(1).jpg

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();
}

我们实验中得出的结果!

IMG_2262(1).jpg

2012-5-28 15:53 上传
(99.53 KB)


IMG_2263(1).jpg

2012-5-28 15:54 上传
(128.85 KB)





有什么问题欢迎提问,大家一起学习,开源硬件,资料来自网络,分享整理快乐!

via - 极客工坊

标签: Arduino教程