Hello guys, I’m developing an example using this camera based on Mr_Arduino code for arduino mega, I am transmitting the data to the PC via serial interface, but the data are not coming properly.
Could you help me ?
Thaks
#include <stdint.h>
#define F_CPU 16000000UL
#include <stdint.h>
#include <avr/io.h>
#include <util/twi.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include<I2C.h>
void wrReg(uint8_t reg,uint8_t dat);
uint8_t rdReg(uint8_t reg);
enum RESOLUTION{VGA,QVGA,QQVGA};
enum COLORSPACE{YUV422,RGB565,BAYER_RGB};
struct regval_list{
uint8_t reg_num;
uint8_t value;
};
void setColorSpace(enum COLORSPACE color);
void setRes(enum RESOLUTION res);
void camInit(void);
#define OV7670_I2C_ADDRESS 0x21
#define camAddr_WR 0x42
#define camAddr_RD 0x43
//register definitions not show...
static void errorD(void){
}
void twiStart(void){
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);//send start
while (!(TWCR & (1<<TWINT))) {}//wait for start to be transmitted
if ((TWSR & 0xF8) != TW_START)
errorD();
}
void twiWriteByte(uint8_t DATA,uint8_t type){
static uint16_t err=5;
TWDR = DATA;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & (1<<TWINT))) {}
if ((TWSR & 0xF8) != type)
errorD();
++err;
}
void twiAddr(uint8_t addr,uint8_t typeTWI){
TWDR = addr;//send address
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0); /* wait for transmission */
if ((TWSR & 0xF8) != typeTWI)
errorD();
}
uint8_t twiRd(uint8_t nack){
if (nack){
TWCR=_BV(TWINT) | _BV(TWEN);
while ((TWCR & _BV(TWINT)) == 0); /* wait for transmission */
if ((TWSR & 0xF8) != TW_MR_DATA_NACK)
errorD();
return TWDR;
}else{
TWCR=_BV(TWINT) | _BV(TWEN) | _BV(TWEA);
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
if ((TWSR & 0xF8) != TW_MR_DATA_ACK)
errorD();
return TWDR;
}
}
void wrReg(uint8_t reg,uint8_t dat){
//send start condition
//PORTG|=1<<5;
twiStart();
twiAddr(camAddr_WR,TW_MT_SLA_ACK);
twiWriteByte(reg,TW_MT_DATA_ACK);
twiWriteByte(dat,TW_MT_DATA_ACK);
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);//send stop
_delay_ms(1);
//PORTG&=~(1<<5);
}
uint8_t rdReg(uint8_t reg){
//PORTG|=1<<5;
uint16_t dat;
twiStart();
twiAddr(camAddr_WR,TW_MT_SLA_ACK);
twiWriteByte(reg,TW_MT_DATA_ACK);
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);//send stop
_delay_ms(1);
twiStart();
twiAddr(camAddr_RD,TW_MR_SLA_ACK);
dat=twiRd(1);
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);//send stop
_delay_ms(1);
//PORTG&=~(1<<5);
return dat;
}
void wrSensorRegs8_8(const struct regval_list reglist[]){
uint8_t reg_addr,reg_val;
const struct regval_list *next = reglist;
while ((reg_addr != 0xff) | (reg_val != 0xff)){
reg_addr = pgm_read_byte(&next->reg_num);
reg_val = pgm_read_byte(&next->value);
wrReg(reg_addr, reg_val);
next++;
}
}
void setColorSpace(enum COLORSPACE color){
switch(color){
case YUV422:
wrSensorRegs8_8(yuv422_ov7670);
break;
case RGB565:
wrSensorRegs8_8(rgb565_ov7670);
{uint8_t temp=rdReg(0x11);
_delay_ms(1);
wrReg(0x11,temp);}//according to the Linux kernel driver rgb565 PCLK needs rewriting
break;
case BAYER_RGB:
wrSensorRegs8_8(bayerRGB_ov7670);
break;
}
}
void setRes(enum RESOLUTION res){
switch(res){
case VGA:
wrReg(REG_COM3,0); // REG_COM3
wrSensorRegs8_8(vga_ov7670);
break;
case QVGA:
wrReg(REG_COM3,4); // REG_COM3 enable scaling
wrSensorRegs8_8(qvga_ov7670);
break;
case QQVGA:
wrReg(REG_COM3,4); // REG_COM3 enable scaling
wrSensorRegs8_8(qqvga_ov7670);
break;
}
}
void camInit(void){
wrReg(0x12, 0x80);//Reset the camera.
_delay_ms(100);
wrSensorRegs8_8(ov7670_default_regs);
wrReg(REG_COM10,32);//PCLK does not toggle on HBLANK.
}
#define useVga
//#define useQvga
//#define useQqvga
static inline void serialWrB(uint8_t dat){
//while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
UDR0=dat;
while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
}
static void StringPgm(const char * str){
do{
serialWrB(pgm_read_byte_near(str));
}while(pgm_read_byte_near(++str));
}
static void captureImg(uint16_t wg,uint16_t hg){
uint16_t lg2;
#ifdef useQvga
uint8_t buf[640];
#elif defined(useQqvga)
uint8_t buf[320];
#endif
serialWrB('R');
serialWrB('D');
serialWrB('Y');
//StringPgm(PSTR("RDY"));
//Wait for vsync it is on pin 3 (counting from 0) portD
while(!(PINE&32));//wait for high
while((PINE&32));//wait for low
#ifdef useVga
while(hg--){
lg2=wg;
while(lg2--){
while((PINE&16));//wait for low
UDR0=PINC;
while(!(PINE&16));//wait for high
}
}
#elif defined(useQvga)
/*We send half of the line while reading then half later */
while(hg--){
uint8_t*b=buf,*b2=buf;
lg2=wg/2;
while(lg2--){
while((PINE&16));//wait for low
*b++=PINC;
while(!(PINE&16));//wait for high
while((PINE&16));//wait for low
*b++=PINC;
UDR0=*b2++;
while(!(PINE&16));//wait for high
}
/* Finish sending the remainder during blanking */
lg2=wg/2;
while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
while(lg2--){
UDR0=*b2++;
while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
}
}
#else
/* This code is very similar to qvga sending code except we have even more blanking time to take advantage of */
while(hg--){
uint8_t*b=buf,*b2=buf;
lg2=wg/5;
while(lg2--){
while((PINE&16));//wait for low
*b++=PINC;
while(!(PINE&16));//wait for high
while((PINE&16));//wait for low
*b++=PINC;
while(!(PINE&16));//wait for high
while((PINE&16));//wait for low
*b++=PINC;
while(!(PINE&16));//wait for high
while((PINE&16));//wait for low
*b++=PINC;
while(!(PINE&16));//wait for high
while((PINE&16));//wait for low
*b++=PINC;
UDR0=*b2++;
while(!(PINE&16));//wait for high
}
/* Finish sending the remainder during blanking */
lg2=320-(wg/5);
while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
while(lg2--){
UDR0=*b2++;
while(!( UCSR0A & (1<<UDRE0)));//wait for byte to transmit
}
}
#endif
}
void setup() {
//cli();
DDRL|=8;
ASSR &= (uint8_t)~(_BV(EXCLK) | _BV(AS2));
//generate 8mhz clock
TCCR5A=67;
TCCR5B=17;
DDRC=0;//set ov7670 pins to input
OCR5A=0;
DDRC=0;
//DDRG|=1<<5;
UBRR0H=0;
UCSR0A|=2;//double speed aysnc
UBRR0L=1;//0 = 2m 1= 1m 3 = 0.5M 2M baud rate = 0 7 = 250k 207 is 9600 baud rate
UCSR0B = (1<<RXEN0)|(1<<TXEN0);//Enable receiver and transmitter
UCSR0C=6;//async 1 stop bit 8bit char no parity bits
ADCSRA=(1<<ADEN)|(1<<ADPS2);//enable ADC
sei();
TWSR&=(uint8_t)~3;//disable prescaler for TWI
TWBR=72;//set to 100khz
camInit();
#ifdef useVga
setRes(VGA);
setColorSpace(BAYER_RGB);
wrReg(0x11,25);
#elif defined(useQvga)
setRes(QVGA);
setColorSpace(YUV422);
wrReg(0x11,12);
#else
setRes(QQVGA);
setColorSpace(YUV422);
wrReg(0x11,3);
#endif
//serialWrB('T');
captureImg(640,480);
//uart_putchar('A');
//initCam(0);
//setColor(BAYER_RGB);
//setRes(VGA);
//uart_putchar('B');
//captureImg(320, 240);
}
void loop() {
captureImg(640,480);
//captureImg(320, 240);
}
Schematic model ov7670 - arduino mega,
PINS D0-D7 => D37 - D30
VYSNC - PIN 3
PCLK - PIN 2
SCIOC - PIN 21
SCIOD - PIN 20
HCLK - PIN D46 (Used two resistors 4.7 K)
RESET - VCC
PWDN - 3.3V
HREF - Not connected