一,准备
- cjmcu 光流传感器 ADNS3080 一个
- arduino nano开发板一个(NANO默认SPI:10(SS),11(MOSI),12(MISO),13(SCK)))
- arduino ide 2.0
- processing 4.0
参考链接:https://github.com/ThomasVandenabeele/rp-adns3080
二,图像代码
1,arduino代码
#include "SPI.h"
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 7); // RX, TX
#define PIN_SS 10
#define PIN_MISO 12
#define PIN_MOSI 11
#define PIN_SCK 13
#define PIN_MOUSECAM_RESET 9
#define PIN_MOUSECAM_CS 10
#define ADNS3080_PIXELS_X 30
#define ADNS3080_PIXELS_Y 30
#define ADNS3080_PRODUCT_ID 0x00
#define ADNS3080_REVISION_ID 0x01
#define ADNS3080_MOTION 0x02
#define ADNS3080_DELTA_X 0x03
#define ADNS3080_DELTA_Y 0x04
#define ADNS3080_SQUAL 0x05
#define ADNS3080_PIXEL_SUM 0x06
#define ADNS3080_MAXIMUM_PIXEL 0x07
#define ADNS3080_CONFIGURATION_BITS 0x0a
#define ADNS3080_EXTENDED_CONFIG 0x0b
#define ADNS3080_DATA_OUT_LOWER 0x0c
#define ADNS3080_DATA_OUT_UPPER 0x0d
#define ADNS3080_SHUTTER_LOWER 0x0e
#define ADNS3080_SHUTTER_UPPER 0x0f
#define ADNS3080_FRAME_PERIOD_LOWER 0x10
#define ADNS3080_FRAME_PERIOD_UPPER 0x11
#define ADNS3080_MOTION_CLEAR 0x12
#define ADNS3080_FRAME_CAPTURE 0x13
#define ADNS3080_SROM_ENABLE 0x14
#define ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER 0x19
#define ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER 0x1a
#define ADNS3080_FRAME_PERIOD_MIN_BOUND_LOWER 0x1b
#define ADNS3080_FRAME_PERIOD_MIN_BOUND_UPPER 0x1c
#define ADNS3080_SHUTTER_MAX_BOUND_LOWER 0x1e
#define ADNS3080_SHUTTER_MAX_BOUND_UPPER 0x1e
#define ADNS3080_SROM_ID 0x1f
#define ADNS3080_OBSERVATION 0x3d
#define ADNS3080_INVERSE_PRODUCT_ID 0x3f
#define ADNS3080_PIXEL_BURST 0x40
#define ADNS3080_MOTION_BURST 0x50
#define ADNS3080_SROM_LOAD 0x60
#define ADNS3080_PRODUCT_ID_VAL 0x17
void mousecam_reset()
{
digitalWrite(PIN_MOUSECAM_RESET,HIGH);
delay(1); // reset pulse >10us
digitalWrite(PIN_MOUSECAM_RESET,LOW);
delay(35); // 35ms from reset to functional
}
int mousecam_init()
{
pinMode(PIN_MOUSECAM_RESET,OUTPUT);
pinMode(PIN_MOUSECAM_CS,OUTPUT);
digitalWrite(PIN_MOUSECAM_CS,HIGH);
mousecam_reset();
int pid = mousecam_read_reg(ADNS3080_PRODUCT_ID);
if(pid != ADNS3080_PRODUCT_ID_VAL)
return -1;
// turn on sensitive mode
mousecam_write_reg(ADNS3080_CONFIGURATION_BITS, 0x19);
return 0;
}
void mousecam_write_reg(int reg, int val)
{
digitalWrite(PIN_MOUSECAM_CS, LOW);
SPI.transfer(reg | 0x80);
SPI.transfer(val);
digitalWrite(PIN_MOUSECAM_CS,HIGH);
delayMicroseconds(50);
}
int mousecam_read_reg(int reg)
{
digitalWrite(PIN_MOUSECAM_CS, LOW);
SPI.transfer(reg);
delayMicroseconds(75);
int ret = SPI.transfer(0xff);
digitalWrite(PIN_MOUSECAM_CS,HIGH);
delayMicroseconds(1);
return ret;
}
struct MD
{
byte motion;
char dx, dy;
byte squal;
word shutter;
byte max_pix;
};
void mousecam_read_motion(struct MD *p)
{
digitalWrite(PIN_MOUSECAM_CS, LOW);
SPI.transfer(ADNS3080_MOTION_BURST);
delayMicroseconds(75);
p->motion = SPI.transfer(0xff);
p->dx = SPI.transfer(0xff);
p->dy = SPI.transfer(0xff);
p->squal = SPI.transfer(0xff);
p->shutter = SPI.transfer(0xff)<<8;
p->shutter |= SPI.transfer(0xff);
p->max_pix = SPI.transfer(0xff);
digitalWrite(PIN_MOUSECAM_CS,HIGH);
delayMicroseconds(5);
}
// pdata must point to an array of size ADNS3080_PIXELS_X x ADNS3080_PIXELS_Y
// you must call mousecam_reset() after this if you want to go back to normal operation
int mousecam_frame_capture(byte *pdata)
{
mousecam_write_reg(ADNS3080_FRAME_CAPTURE,0x83);
digitalWrite(PIN_MOUSECAM_CS, LOW);
SPI.transfer(ADNS3080_PIXEL_BURST);
delayMicroseconds(50);
int pix;
byte started = 0;
int count;
int timeout = 0;
int ret = 0;
for(count = 0; count < ADNS3080_PIXELS_X * ADNS3080_PIXELS_Y; )
{
pix = SPI.transfer(0xff);
delayMicroseconds(10);
if(started==0)
{
if(pix&0x40)
started = 1;
else
{
timeout++;
if(timeout==100)
{
ret = -1;
break;
}
}
}
if(started==1)
{
pdata[count++] = (pix & 0x3f)<<2; // scale to normal grayscale byte range
}
}
digitalWrite(PIN_MOUSECAM_CS,HIGH);
delayMicroseconds(14);
return ret;
}
void setup()
{
pinMode(PIN_SS,OUTPUT);
pinMode(PIN_MISO,INPUT);
pinMode(PIN_MOSI,OUTPUT);
pinMode(PIN_SCK,OUTPUT);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV32);
SPI.setDataMode(SPI_MODE3);
SPI.setBitOrder(MSBFIRST);
Serial.begin(115200);
if(mousecam_init()==-1)
{
Serial.println("Mouse cam failed to init");
while(1);
}
}
char asciiart(int k)
{
static char foo[] = "WX86*3I>!;~:,`. ";
return foo[k>>4];
Serial.begin(9600);
}
byte frame[ADNS3080_PIXELS_X * ADNS3080_PIXELS_Y];
void loop()
{
//#if 1
// if enabled this section grabs frames and outputs them as ascii art
if(mousecam_frame_capture(frame)==0)
{
int i,j,k;
Serial.print("S");
Serial.println();
for(i=0, k=0; i<ADNS3080_PIXELS_Y; i++)
{
for(j=0; j<ADNS3080_PIXELS_X; j++, k++)
{
Serial.print(frame[k]);//asciiart(frame[k]));
Serial.print('-');
}
Serial.println();
}
}
//Serial.print("E");
//Serial.println();
////Serial.println();
delay(100);
//#else
// if enabled this section produces a bar graph of the surface quality that can be used to focus the camera
// also drawn is the average pixel value 0-63 and the shutter speed and the motion dx,dy.
//int val = mousecam_read_reg(ADNS3080_PIXEL_SUM);
//MD md;
//mousecam_read_motion(&md);
/*
for(int i=0; i<md.squal/4; i++)
Serial.print('*');
Serial.print(' ');
Serial.print((val*100)/351);
Serial.print(' ');
*/
//Serial.print(md.shutter); Serial.print(" (");
//Serial.print("I");
/*int X = (int)md.dx;
int Y = (int)md.dy;
if(X > -1) Serial.print("+");
if(X < 0) Serial.print("-");
if(abs(X) < 10) Serial.print("0");
Serial.print(abs(X));
Serial.print(',');
if(Y > -1) Serial.print("+");
if(Y < 0) Serial.print("-");
if(abs(Y) < 10) Serial.print("0");
Serial.println(abs(Y));
/*
Serial.print((int)md.dx); Serial.print(',');
Serial.println((int)md.dy); //Serial.println(')');
// Serial.println(md.max_pix);
*/
//delay(20);
//*/
//#endif
}
2,processing
注意要在插件管理里面安装javafx
import processing.javafx.*;
import processing.serial.*;
Serial myPort;
String myRawString = "";
int[][] image = new int[30][30];
int row = 0;
int col = 0;
int driftX = 0;
int driftY = 0;
void setup() {
size(300, 330, FX2D);
pixelDensity(2);
myPort = new Serial(this, "COM4", 115200);//这里写自己arduino nano的串口号
}
void draw() {
fill(255, 0, 0);
rect(0, 0, 300, 30);
fill(255, 255, 0);
textSize(15);
text("Ling & Thomas", 10, 20);
while (myPort.available() > 0) {
myRawString = myPort.readStringUntil('\n');
if (myRawString != null) {
if(myRawString.charAt(0) == 'S' | myRawString.charAt(0) == 'E'){
row = 0;
col = 0;
}
if(myRawString.charAt(0) == 'I'){
String strX = myRawString.substring(1, 4);
String strY = myRawString.substring(5, 8);
driftX = parseInt(strX)*-1;
driftY = parseInt(strY);
//println("X: "+ driftX);
//println("Y: "+ driftY);
fill(255, 255, 0);
textSize(15);
text(driftX, 210, 20);
text(driftY, 280, 20);
}
else{
int[] line = int(split(myRawString, "-"));
if(line.length > 30 && row < 30){
for (int i = 0; i < 30; i = i+1) {
image[i][row] = line[i];
stroke(image[i][row]);
fill(image[i][row]);
rect(i*10, row*10+30, 10, 10);
}
row++;
}
}
}
}
}
3,如图
三,数据代码
直接在arduino的库里面搜索3080,然后就看到了该传感器库,安装后有例程。
声明:
本文采用
BY-NC-SA
协议进行授权,如无注明均为原创,转载请注明转自
走着的小站
本文地址: ADNS3080光流传感器的arduino编程测试
本文地址: ADNS3080光流传感器的arduino编程测试