3D point cloud scanner with OV7670 camera and line laser.
Dependencies: ADXL345_I2C_ HMC5843_ OV7670_ok SDFileSystem ST7735_TFT Servo mbed
Fork of OV7670_edm_full by
3D point cloud scanner with OV7670 FIFO camera and line laser. I take the brightest pixels in an image, I measure their horizontal displacement to deduce a depth value, and I generate XYZ coordinates. The camera is rotating, and I know the angle, so I can map 3D space in cylindrical coordinates. The home of the project is http://angelomottolese.eu.ai/sitoScanner.html
main.cpp
- Committer:
- rulla
- Date:
- 2017-10-03
- Revision:
- 3:9244869157bd
- Parent:
- 2:4ebec58ffaca
File content as of revision 3:9244869157bd:
//3D Scanner //2017 Angelo Mottolese mottoleseangelo@gmail.com #include "mbed.h" #include "OV7670.h" #include "ST7735_TFT.h" #include "ADXL345_I2C.h" #include "HMC5843.h" #include "SDFileSystem.h" #include "Servo.h" #define SIZEX 320 #define SIZEY 240 #define SIZE SIZEX*SIZEY #define LABVIEW_MODE 1 #define TRANSFER_SIZE 4 #define N_VAR 14 //LocalFileSystem local("local"); // Create the local filesystem under the name "local" OV7670 cam( p28,p27, // SDA,SCL(I2C / SCCB) p23,NC,p25, // VSYNC,HREF,WEN(FIFO) Port0,0x07878000,//PortIn(p18,p17,p16,p15,p11,p12,p14,p13) is D7-D0 p26,p29,p30) ; // RRST,OE,RCLK ST7735_TFT TFT(p5, p6, p7, p8, p9, p10,"TFT"); // mosi, miso, sclk, cs, rs, reset // SDA, nc, SCK,CS,A0,RESET = mosi, miso, sclk, cs, rs, reset HMC5843 compass(p28, p27); ADXL345_I2C accelerometer(p28, p27); //SDFileSystem sd(p5, p6, p7, p21, "sd"); // the pinout on the mbed Cool Components workshop board //nRF24L01P my_nrf24l01p(p5, p6, p7, p24, p21, p20); // mosi, miso, sck, csn, ce, irq Servo yaw(p21); Serial pc(USBTX,USBRX); Timer tempo; AnalogIn pot(p20); float Complementary(float newAngle, int looptime); float Complementary2(float newAngle, int looptime); double kalman_update(int index,double measurement); float kalmanCalculate(float newAngle, int looptime); void accMagInit(void); void ahrs(void); void kalman_init(void); void showImage(void); void image_minmax(void); void processImage(void); void sdInit(void); void nrfpInit(void); void countdown(void); extern "C" void mbed_reset(); double q[N_VAR]; //process noise covariance double rk[N_VAR]; //measurement noise covariance double value[N_VAR]; //value double p[N_VAR]; //estimation error covariance double k[N_VAR]; //kalman gain int i=0, loopN=0, l=0; float mv=0.0,servoHead=0.0; int thr=5; float xrot=0.0,yrot=0.0,zrot=0.0, vx=0.0,vy=0.0,vz=0.0; int ax=0,ay=0,az=0,ax0,ay0,az0; int mx=0,my=0,mz=0,mx0,my0,mz0; double xh=0.0, yh=0.0, head=0.0; double ca=0.0, cb=0.0, cc=0.0; double sa=0.0, sb=0.0,sc=0.0; double fx,fy,fz; uint16_t thri=3,thrr=3,thrg=4; uint16_t max_red,max_blue, max_green,min_blue,min_green,min_red; uint16_t colour=0,r,g,b; int x=0,y=0, lineacc,cnt=0,x0[SIZEY]; uint16_t bank0,bank1; int ok=0; uint16_t mr=0,mb=0,mg=0,id=0; // FILE *out=fopen("/local/world.txt","w"); int main() { // if ( out == NULL ) error("Could not open file.\r\n"); //fprintf(out,"v 0.0 0.0 0.0\n"); pc.baud(115200); yaw=0.0; //////////////////////Camera and TFT init TFT.set_orientation(3); //TFT.background(Black); TFT.cls(); cam.Reset() ; cam.InitQQVGA(SIZEX) ; pc.baud(115200); kalman_init(); accMagInit(); //nrfpInit(); //sdInit(); /////////////////////////////////// Loop control//////////////////////////////////////////////////// int j=0; for(j=1; j>0; j--) { if(LABVIEW_MODE==0) pc.printf("Posizionamento %d s\n", j); tempo.start(); while(tempo.read()<0.5) showImage(); tempo.stop(); tempo.reset(); } //countdown(); image_minmax(); // while(1) { //tempo.start(); ahrs(); ///////////Image Acquisition and Processing // if((hd[0]+0.22)<hd[1] || (hd[0]-0.22)>hd[1]){ //Heading noise gate ok=0; //if(loopN%20==0) TFT.cls(); //Misura intensità max e min if(loopN%100==0 || loopN==0) image_minmax(); //Se il numero di pixel validi è piccolo // printf(" SCANNING.\n"); while(1) { ahrs(); image_minmax(); processImage(); loopN++; yaw=kalman_update(12,mv); servoHead=mv*1.5768863175; // wait_ms(20); } /* for(mv=1.0; mv>0.0; mv-=0.01) { ahrs(); image_minmax(); processImage(); loopN++; yaw=kalman_update(12,mv); servoHead=mv*1.5768863175; wait_ms(20); } yaw=kalman_update(12,0.0);*/ //fclose(out); // printf(" END\n"); // tempo.stop(); // printf("Time taken= %f seconds, OK=%d\n", tempo.read(),ok); // tempo.reset(); // }//Fine while(1) // mbed_reset(); } double kalman_update(int index,double measurement) { //prediction update //omit x = x p[index]+= q[index]; //measurement update k[index] = p[index] / (p[index] + rk[index]); value[index] += k[index] * (measurement - value[index]); p[index] *= (1 - k[index]); //fprintf(out,"%f %f \r\n",p,k); return value[index]; } void kalman_init(void) { for(l=0; l<N_VAR; l++) { q[l]=0.001; //process noise covariance rk[l]=0.1; //measurement noise covariance p[l]=0.0; //estimation error covariance k[l]=0.0; //kalman gain value[l]=0.0; } } ///////////////////////////////////////////SD Card init void sdInit(void) { /* mkdir("/sd/", 0777); FILE *fp = fopen("/sd/worldSD.obj", "w"); if(fp == NULL) error("Could not open file for write\n"); fprintf(fp, "World mapping"); fclose(fp); */ } ////////////////////////////AHRS////////////////// void accMagInit(void) { int breadings[3] = {0, 0, 0}; int bhmcreadings[3]; char buffer[3]; // if(LABVIEW_MODE==0) pc.printf("Starting ADXL345 test...\n"); // if(LABVIEW_MODE==0) pc.printf("Device ID is: 0x%02x\n", accelerometer.getDevId()); accelerometer.setPowerControl(0x00); accelerometer.setDataFormatControl(0x0B); accelerometer.setDataRate(ADXL345_3200HZ); accelerometer.setPowerControl(0x08); compass.getAddress(buffer); // if(LABVIEW_MODE==0) pc.printf("Magnetic Compass Id=%c%c%c \n\r",buffer[0],buffer[1],buffer[2]); compass.setDefault(); wait(.1); for(i=0; i<50; i++) { accelerometer.getOutput(breadings); //13-bit, sign extended values. compass.readData(bhmcreadings); wait(0.1); ax+=(int16_t)(breadings[0]); ay+=(int16_t)(breadings[1]); az+=(int16_t)(breadings[2]); mx+=(int16_t)(bhmcreadings[0]); my+=(int16_t)(bhmcreadings[1]); mz+=(int16_t)(bhmcreadings[2]); } ax0=ax/50; ay0=ay/50; az0=az/50; mx0=mx/50; my0=my/50; mz0=mz/50; ax=0; ay=0; az=0; mx=0; my=0; mz=0; } void ahrs(void) { cnt=0; int accelero=0, deadr=0; if(accelero==1) { float x1=0.0,y1=0.0,z1=0.0,x2=0.0,y2=0.0,z2=0.0,xd=0.0,yd=0.0,zd=0.0; float aax=0.0,aay=0.0,aaz=0.0; int readings[3] = {0, 0, 0}; int hmcreadings[3]; accelerometer.getOutput(readings); compass.readData(hmcreadings); //13-bit, sign extended values. cnt++; ax+=(int16_t)(readings[0]); ay+=(int16_t)(readings[1]); az+=(int16_t)(readings[2]); ax-=ax0; ay-=ay0; az-=az0; mx+=(int16_t)(hmcreadings[0]); my+=(int16_t)(hmcreadings[1]); mz+=(int16_t)(hmcreadings[2]); mx-=mx0; my-=my0; mz-=mz0; wait(0.1); xd=(double)(ax); yd=(double)(ay); zd=(double)(az); aax=kalman_update(9,xd); //Kalman to accelerometer aay=kalman_update(10,yd); aaz=kalman_update(11,-zd); if(deadr==1) { x1+=kalman_update(3,aax); y1+= kalman_update(4,aay); z1+= kalman_update(5,aaz); if(aax<=1.6420 && aax>=-1.6420 ) x1=0.0; if(aay<=1.2315 && aay>=-1.1325 ) y1=0.0; if(aaz<=8.374 && aaz>=-8.374 ) z1=0.0; x2+=kalman_update(6,x1); y2+=kalman_update(7,y1); z2+=kalman_update(8,z1); } double xAngle=-0.00609*aay; double yAngle=0.00609*aax; double mmx=(double)(mx); double mmy=(double)(my); double mmz=(double)(mz); fx=kalman_update(0,xAngle); fy=kalman_update(1,yAngle); ca = cos(fx);//theta cb = cos(fy);//phi sa = sin(fx); sb = sin(fy); double yh=mmz*sb-mmy*cb; double xh=+mmx*ca+mmy*sa*sb+mmz*sa*cb; double head=atan2(yh,xh); fz=kalman_update(2,head); } //if(accelero==0) { fz=servoHead; fz=pot.read(); fz-=0.1; fz*=6.2831168863175; fz=3.14-fz; cc = cos(fz); sc = sin(fz); //if(LABVIEW_MODE==0) pc.printf("%f %f %f %f %f %f %f %f %f\n",fx,fy,fz,x2,y2,z2,kalman_update(9,x2),kalman_update(10,y2),kalman_update(11,z2)); cnt=0; ax=0; ay=0; az=0; } /////////////////////CAMERA FUNCTIONS///////////////////// void image_minmax(void) { for(id=0;id<SIZEY;id++) x0[id]=0; max_red=0;max_blue=0; max_green=0;min_blue=200;min_green=200;min_red=200; cam.CaptureNext() ; while (cam.CaptureDone()==0) ; cam.ReadStart(); for (y = 0; y < SIZEY; y++) { for ( x= 0; x < SIZEX; x++) { bank0 = cam.ReadOneByte(); bank1 = cam.ReadOneByte(); r=((bank1 & 0x1f)) ; g= (((bank0<<3)&0x38 )|((bank1>>5)&0x7)) & 0x3f; b=((bank0 & 0xf8)>>3 ); /* if(b>max_blue) { max_blue=b; if(max_green<g) max_green=g; if(max_red<r) max_red=r; if(min_blue>b) min_blue=b; if(min_green>g) min_green=g; if(min_red>r) min_red=r; mr+=r; mb+=b; mg+=g; id++; }*/ if(r>max_red) { max_red=r; if(max_green<g) max_green=g; if(max_blue<b) max_blue=b; if(min_blue>b) min_blue=b; if(min_green>g) min_green=g; if(min_red>r) min_red=r; mr+=r; mb+=b; mg+=g; id++; } } } cam.ReadStop() ; } void processImage(void) { cnt=0; double xrot,yrot,zrot; cam.CaptureNext() ; while (cam.CaptureDone()==0) ; cam.ReadStart(); for (y = 0; y < SIZEY; y++) { for ( x= 0; x < SIZEX; x++) { bank0 = cam.ReadOneByte(); bank1 = cam.ReadOneByte(); r=((bank1 & 0x1f)) ; g= (((bank0<<3)&0x38 )|((bank1>>5)&0x7)) & 0x3f; b=((bank0 & 0xf8)>>3 ); //if(b>=(mb-thri) && r<=(mr+thrr) ) { if(r>=(max_red-thrr) && b>=(max_blue-thri)) { lineacc+=x; cnt++; } } if(cnt>1) { x0[y]=lineacc/cnt; ok++; } lineacc=0; cnt=0; } cam.ReadStop() ; for(y=0;y<SIZEY;y++){ vy=(double)(SIZEX)-(double)x0[y];//vy*sc vx=(double)(SIZEX)-(double)(SIZEX)*cc;//vy*cc vx=vy*cc;//vy*cc yrot=vy*sc; zrot=y*0.6; TFT.pixel(x0[y],y,x0[y]*10); // if(LABVIEW_MODE==0) pc.printf("v %f. %f. %f\n",xrot,yrot,zrot); if(LABVIEW_MODE==0) pc.printf("%f %f %f %f ",vx,vy,vz,fz); if(LABVIEW_MODE==1) pc.printf("%.3f,%.3f,%.3f\n",vx,yrot,zrot); } } void showImage(void) { cam.CaptureNext() ; while (cam.CaptureDone()==0) ; cam.ReadStart(); for (y = 0; y < SIZEY; y++) { for ( x= 0; x < SIZEX; x++) { bank0 = cam.ReadOneByte(); bank1 = cam.ReadOneByte(); r=((bank1 & 0x1f)) ; g= (((bank0<<3)&0x38 )|((bank1>>5)&0x7)) & 0x3f; b=((bank0 & 0xf8)>>3 ); colour = (((r<<11)&0xF800)|((g<<5)&0x7E0)| (b&0x1f)); TFT.pixel(x,y,colour); } } cam.ReadStop() ; } void countdown(void) { int i; for(i=3; i>0; i--) { showImage(); wait(1); if(LABVIEW_MODE==0) pc.printf("Acquisisco fra %d s\n",i); } }