分享

Arduino+TTL摄像头自制拉风数码相机

 开启美好每一天 2014-01-14

当别人都是长枪大炮地挤在一起拍照时,你夹在当中用狗头来照相,当然显不出你的个性.如果换成是自己DIY的个性化数码相机,那就完全不一样了.

Arduino支持SPI或TTL接口的摄像头(30万像素,最高画质640*480).所以自己制作的话就很容易了.目前国内外使用的TTL摄像头基本只有一种,就是采用中星微VC0706芯片的产品.这种TTL/RS232接口的摄像头万能的淘宝上有卖的,自己选就行了.还有一种是同时带SPI和TTL/RS232接口的.SPI的速度远快于TTL的,所以如果有要求更快处理速度的应用,可以考虑使用SPI的版本.

玩Arduino的Ada女士网站上有这个摄像头的运行库和例程,可以直接下载并测试.

从淘宝上买的摄像头没注意,发过来的是RS232的版本,所以需要把MAX3232的芯片拆掉后,才能接到Arduino UNO的板子上.由于摄像头输出的TTL电平是3.3V的,所以在与5V的Arduino板接线时,输入端最好用两个10K左右的电阻做一下分压,以免人品不好损坏电路.

自己DIY相机的元件清单:

1/Arduino板一个,我用的是UNO版本的

2/VC0706摄像头一个

3/按钮2个

4/带开关的4节5号电池盒一个

5/10K电阻3个

6/LED一个

7/SD转接板一个

8/格式化为FAT格式的SD卡一张(如果用shield板的话,TF卡也可以)

9/导线若干

10/面包板一个

国外有个Arduino+TTL摄像头的网页,国内有网页还翻译成了中文.那个制作的作者到目前为止还没有公布代码.他用的是锂电板,变压成5V给UNO使用.但那个方案是有问题的.因为UNO板子外接电源时,不能自动工作,只有按RESET复位按钮电路才能正常工作.但他公布的电路图中,并没有外接复位按钮的部分.估计这也是其没有公布源代码的原因之一吧.

接线如下图.这个图是之前的版本,我的这个图也没有接复位按钮,只接了拍照按钮.按照按钮的接线应该接到Digital接口7上.图中的接线是之前随便接的.不正确.如果是使用USB来供电,电路是正常没问题的.如果外接电池的话,需要按板子上的复位按钮才行.图中也没有接存储指示灯的LED.实际接线时,直接串2K以上的电阻到digital 13脚并接地即可.

 

摄像头的TTL接线并不是接于UNO板的物理TX和RX脚,而是接于digital 2/3脚.通过虚拟串口来进行通信.

UNO与SD的通信,通过SPI接口,需要根据SD转接板的接口定义来设置.我的板子接线是这样的,请注意接线颜色:

 

 

 UNO端从digital 10-13,接线颜色分别为白绿蓝黄.

 

 Ada女士的TTL摄像头例程并不能用于相机的功能.所以需要做修改,以下是我根据接线情况修改后的拍照程序,使用Arduino 1.04版IDE编译通过:

  

#include <Adafruit_VC0706.h>
#include <SD.h>

#include <SoftwareSerial.h>        

#define chipSelect 10
#define Button 7  //定义拍照按钮针脚为7
int ButtonVal=0;  //变量ButtonVal用来存储拍照按钮状态


#if ARDUINO >= 100
// 定义虚拟串口,对于Uno板摄像头TX脚连到Digital pin 2, 摄像头RX脚连到Digital pin 3:
SoftwareSerial cameraconnection = SoftwareSerial(2, 3);
#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);

void setup() {

          // 使用硬件SPI时, SS必须设为输出
          #if !defined(SOFTWARE_SPI)
          #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
            if(chipSelect != 53) pinMode(53, OUTPUT); // 使用mega2560时SS设置
          #else
            if(chipSelect != 10) pinMode(10, OUTPUT); // 使用UNO时SS设置

          #endif
          #endif

//串口监控输出及定义: 

 Serial.begin(9600);
  pinMode(Button, INPUT);
  Serial.println("VC0706 Camera snapshot test");
 
              // 判断SD卡是否插入并初始化:
            if (!SD.begin(chipSelect)) {
              Serial.println("Card failed, or not present");
              // 停止:
              return;
            } 
 
  // 初始化摄像头
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // 输出摄像头版本
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

  // 设置拍照尺寸,可设为640x480, 320x240及160x120
  // 尺寸越大数据传输时间越长!
 
  cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  //cam.setImageSize(VC0706_160x120);          // small

  // 可从摄像头读取图片大小

  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

}

void loop() {
//按拍照按钮拍一张照片
ButtonVal=digitalRead(Button);
if (ButtonVal==HIGH){
                            Serial.println("Snaping Picture...");
                            delay(20);
                         
                            if (! cam.takePicture())
                              Serial.println("Failed to snap!");
                            else
                              Serial.println("Picture taken!");
                           
                            // 以IMAGExx.JPG为文件名创建图片文件
                            char filename[13];
                            strcpy(filename, "IMAGE00.JPG");
                            for (int i = 0; i < 99; i++) {
                              filename[5] = '0' + i/10;
                              filename[6] = '0' + i%10;
                              if (! SD.exists(filename)) {
                                break;
                              }
                            }
                           
                            // 打开图像文件并写入
                            File imgFile = SD.open(filename, FILE_WRITE);
                         
                            // 获取图像文件大小
                            uint16_t jpglen = cam.frameLength();
                            Serial.print("Storing ");
                            Serial.print(jpglen, DEC);
                            Serial.print(" byte image.");
                         
                            int32_t time = millis();
                            pinMode(8, OUTPUT);
                            // 读数据到 # bytes!
                            byte wCount = 0; // 计数 # 来写
                            while (jpglen > 0) {
                              // 一次读取 32 bytes;
                              uint8_t *buffer;
                              uint8_t bytesToRead = min(32, jpglen); 

                              buffer = cam.readPicture(bytesToRead);
                              imgFile.write(buffer, bytesToRead);
                              if(++wCount >= 64) { // 每2K发个反馈,以避免出现锁定现象
                                Serial.print('.');
                                wCount = 0;
                              }
                              //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
                              jpglen -= bytesToRead;
                            }
                            imgFile.close();
                         
                            time = millis() - time;
                            Serial.println("done!");
                            Serial.print(time); Serial.println(" ms elapsed");
                    }
                  cam.begin();  //摄像头重新初始清缓存
                  ButtonVal=0;  //按钮值重新设为低 
}

串口的读取速度是很慢的,640*480的照片,存储过程大约需要15秒左右.

这个摄像头默认的通信速度为38400.如果改成57600会快不少.但在面包板上试验时,可能是因为这种面包板接线电气特性问题,存储时会出问题.有可能使用焊接的时候会好一些.把摄像头默认速度改为57600可以使用中星微的官方VC0706CommTool程序设置.设置完成后断电再加电即可.

当然,改了摄像头的默认速度后,也需要修改库里面定义的通信速度,修改方法:

将摄像头库里面的Adafruit_VC0706.h文件:

  boolean begin(uint16_t baud = 38400);

  里面的38400改为57600即可.

  程序调试无误后,就可以写到UNO板里.然后根据国外的那个人做的外壳样式,用纸壳做个个性化的外壳,把这些东西装上即可.最好焊接一下.以免出问题.

  简单地把DIY个性照相机的过程写了一下.有些细节做了省略.可能并不适合新手.见谅.

 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多