Link to home
Start Free TrialLog in
Avatar of mf55
mf55

asked on

Interfacing a camera (OV6620) with a PIC (16F877A)

I have a problem with my codes, i was wondering if someone could help me....
I'm using an OV6620 camera with a PIC 16F877A microcontroller. I am trying to have my camera identify lines on the road (specifically, highways). This camera will be mounted on a toy car and will be demonstrated using a black bristolboard with 2 white lines. When the left line is out of sight, the LEFT LED will go on and when the right Line is out of sight, the Right LED will go on. When neither lines show, the 2 LED's along with a buzzer will go on. {The LED's and Buzzer are connected on a circuit board to Port D of the PIC}

The camera will be communicating with the PIC through 8 bit parallel communication. The PIC will be receiving the information through port B. In order for the camera to be initialized, I need to send command(s) through the I2C from the PIC to the camera. My biggest problem is writing the code to initialize the camera through I2C, and set the ports in the PIC as inputs and outputs. I'm using C programming and a high tech PIC C compiler through MPLAB to compile my codes.  
Avatar of josgood
josgood
Flag of United States of America image

If you don't have a datasheet from MicroChip or some other documentation on this PIC, you should get it.

I did a similar project several years ago.  I don't have the datasheet any more, but I do have some code.  This is one of those times when I wish I had written better comments.

It looks as though I had output enabled on port A, with bits normally low.  The commands I issued were "IOA=0;" and OEA=0xff;".   I believe those commands mean "set the port A outputs to 0" and "enable port A output".  You'll have to check the data sheet to confirm.

I used a macro
    #define WAIT_FOR_TRANSFER while ((I2CS & 1) == 0);
which I believe is waiting for the I2C to go idle

My read/write command was implemented as
            I2CTL &= ~bm400KHZ;             // 100 KHZ communication
            index ^= 1;                     // toggle LED states
            //
            // Read/Write from the camera
            //
            // 1st byte is the device's I2C Write address
            I2CS  = 0x80;               // Start bit asserted
            I2DAT = I2C;                // Device's I2C address
            WAIT_FOR_TRANSFER           // Wait for transfer to complete
            statusByte = I2CS;          // This is for the port scan
            //
            // 2nd byte is the register to be read or written
            I2DAT = REG;                //
            WAIT_FOR_TRANSFER           // Wait for transfer to complete
            //
            // Read from the camera
            //
            if (IN) {
                //
                // 3rd byte is the device's I2C Read address
                I2CS  = 0x80;               // Start bit asserted
                I2DAT = I2C | 1;            // Add read bit to device's address
                WAIT_FOR_TRANSFER           // Wait for transfer to complete
                //
                // 4th byte is the data from the device's register
                I2CS  = 0x20;               // Last-Read bit asserted
                a = I2DAT;                  // Cause data to be clocked in
                PIC 16F877A           // Wait for transfer to complete
                rcvByte = I2DAT;            // Read the actual data
            //
            //  Write to the camera
            //
            } else {
                //
                // 3rd byte is the device's I2C Read address
                I2DAT = VAL;                // Output the register value
                WAIT_FOR_TRANSFER           // Wait for transfer to complete
            }
            //
            // Assert stop on the bus
            I2CS  = 0x40;                   // ..Stop bit asserted
            I2DAT = 0xAA;                   // ..Dummy data

Hope this helps.

Avatar of mf55
mf55

ASKER

do u know how to initialize the ports in C???and i also need to send commands to set the camera's configuration through the I2C, this has to be written in C language also using the HITECH compiler.
these codes are in assembly and i have no idea how to do the rest of my project using assembly that's why i cant using them, thank you very much though.
I recall using in() and out() functions years ago, but a quick search of ANSI C doesn't show them.  HITECH C may provide functions like these.

You might also see if HiTech C provides mixed C and assembly programming -- the usual keyword is ASM.  I'd expect to be able to write something like
asm {
   I2CS = 0x80;
}

There may also be a specialized library, provided by HiTech, for I2C I/O.

Those are my best guesses.

Here also is a link to some sample code.  I note there is sample code for I2C I/O.

http://www.microchipc.com/sourcecode/

Hope this helps.
Avatar of mf55

ASKER

i looked through the manual for HITECH compilers and i couldnt find anything about I2C.the link u gave me is not openning. do u know is I2C on pic is concidered as a normal I/O Pin??besides, im gonna be sending commands to the camera, do u have any idea on how to send comands??in what language they should be written???am i supposed to look for the ASCII equivalent for each letter??thank you very much for your time it's very appreciated...
You are very welcome for the time spent.

Please try the link again.  It opened for me and I was able to view the I2C example code.  

One I2C sample project is specifically for the PIC16F877.  I believe this code sample will answer your I2C questions.

If you can't open the link, then go to their home site http://www.microchipc.com/ and navigate from there.

With respect to your question on the camera commands, you need a data sheet.  This is the information you need to see what the commands look like.  I expect you will end up creating a multi-byte message packet and then transmitting that packet, byte by byte, to the camera.

The camera vendor should be able to provide a data sheet.  

I did a quick Google for "OV6620 camera datasheet".  There were several matches, but none led immediately to the answer you're looking for.  I suggest you try the search -- it may take some time to track down an actual data sheet.

Let me know how its goes.

Joe

Avatar of mf55

ASKER

I followed the link, The I2C code is perfect, thank you very much.
im gonna put the codes together today,i'll let u know how it goes.
Thanks again.
Samir
Avatar of mf55

ASKER

Hi, It's me again.
i finished writting my codes and everything works perfect except when i try to compare a variable that is stored in one of the ports it's giving me an error. again the compiler im using is HITECH PIC C compiler. the code im using is: if ( pin >= 60 )                                    array[y][x] = 1;
      else
      array[y][x] = 0;
im getting the following error:
Error   [491] ; . can't find 0xCB11 words for psect "rbss_0" in segment "BANK0"
                  
Not knowing the code, I can only give general advice.

1)  Determine whether the problem is with referencing pin or with referencing the array location.  I suggest (temporarily) replacing array[y][x] with some scalar that you know you can write to.
2)  If this works OK (you don't get the error), then the problem likely is that array + y*x*sizeof(your type) gives you an address that is out of range for bank 0.
3)  Otherwise the problem is with the reference to pin and I don't see how that could be a problem.

Actually you could just add some code that computes y*x*sizeof(your type).

Hack around in this manner for a little bit and the problem should become clear to you.
Avatar of mf55

ASKER

im gonna include the code, when i take out the part:{
                        if ( pin > 60 )
                        array[y][x] = 1;
                        else
                        array[y][x] = 0;                                                                 }
it compiles.
here is the code, it's an algorithm to detect lines on the road, it compiles perfect on any other compiler, but when i assign the ports and stuff it gives me the error.maybe my understanding of how the pic works is wrong.
Code:
#include <pic.h>
#include <stdio.h>

#define RHEIGHT 292
#define HEIGHT 73
#define WIDTH 356

int aData [WIDTH];
TRISD=0xFF;      //initialize port B as Input
TRISC=0x00; //initialize port D as an output
pin=PORTD; // decimal
/*
      mark = 1 --- nothing all black
      mark = 2 --- right light
      mark = 3 --- left light
      mark = 4 --- normal
      mark = 5 --- line right in the middle

      0 represents black
      1 represents white
*/

int dataAnalyze (void)
{
      int x, mark = 0;
      int leftCount = 0;
      int rightCount = 0;
      int result;


      for (x = 0; x < WIDTH; x++)
      {
            /*
                  first value is a 0 so there is a possibility of all of them being 0
                  so we set mark as 1
            */
            if ( aData[x] == 0 )
            {
                  mark = 1;
                  leftCount++;
                  /* set left counter, in case of a situation where 0011000
                        in where we would need to keep track of the 0's on the left and right
                        in order to know which light should go off */
                  continue;
            }
            else
            {
                  /* in this block 1 has gone of for the first time */
                  if ( mark == 1 )
                        mark = 2; // since there was 0's before the right side has been set so the right light should go off in this scenario
                  else
                        mark = 3; // otherwise no 0's were gone of in the first time so left is a possibility
                  x = x + 1;
                  for (x; x < WIDTH; x++)
                  {
                        if ( aData[x] == 0 )// here a 0 goes off so scenario is at 00001100
                        {
                              rightCount++;      // need to keep track of the 0s on the right side
                              x = x + 1;
                              for (x; x < WIDTH; x++)
                              {
                                    rightCount++;
                                    if ( aData[x] == 1 ) // a 1 has gone of so scenario is at 10001 or 0111101 so that means we got a perfect scenario
                                    {
                                          mark = 4;
                                          break;
                                    }
                              }
                        }
      
                        if (mark == 4)
                              break;
                  }
            }

            if ( mark == 4 )
                  break;
      }
      if (mark == 2) // here the count values are checked to determine if left should go off or right
      {
            if (leftCount < rightCount)
                  mark = 3;
            else if (leftCount == rightCount)
                  mark = 5;
      }

      return mark; // return the value
}

void main (void)
{      
      /* variable declaration */
      int pin;
      int array[HEIGHT][WIDTH];
      int c1, c0;
      int line_check, x, y;
      int c, result;
      
                  
      while (1)
      {
            

            for (y=0; y < RHEIGHT; y++) //292
            {
                  line_check = y%4; //checks 4 lines
                  if (line_check == 0)
                  {
                        for (x=0; x < WIDTH; x++)
                                          }
            }{
                              if ( pin > 60 )
                                    array[y][x] = 1; // repersents white
                              else
                                    array[y][x] = 0;      //represents black
                        }


            /* makes a single array of width 356 with 1/0s to rep white or black for analyzation*/

            for (x = 0; x < WIDTH; x++)
            {
                  c1 = 0;
                  c0 = 0;
                  for (y=0; y < HEIGHT; y++)
                  {
                        if (array[y][x] == 1 )
                              c1++;
                        else
                              c0++;
                  }
                  if (c1 > c0)
                        aData[x] = 1;
                  else
                        aData[x] = 0;
            }
            
            /* result stored array */
            result = dataAnalyze();
             
            if (result == 0)
                  printf ("0");
            else if (result == 1)
                  printf ("1");
            else if (result == 2)
                  printf ("2");
            else if (result == 3)
                  printf ("3");
            else if (result == 4)
                  printf ("4");
            else
                  printf ("5");
      }
}

Seems to me there is a mismatch between the loop parameters and array size
#define RHEIGHT 292
#define HEIGHT 73
#define WIDTH 356
...
      int array[HEIGHT][WIDTH];
....
         for (y=0; y < RHEIGHT; y++) //292
...
Joe
Avatar of mf55

ASKER

i dont think so, because im down sampling the image:
  for (y=0; y < RHEIGHT; y++) //292
            {
                  line_check = y%4; //checks 4 lines
                  if (line_check == 0)
                  {
                        for (x=0; x < WIDTH; x++)
                                          }
so HEIGHT is the new actual height of the image.
I have to run out for a few minutes, but let me give you a short answer.
  for (y=0; y < RHEIGHT; y++) //292
so y can go to 292
array[y][x] = 1; // repersents white
so array[292-1][356-1] is possible
      int array[HEIGHT][WIDTH];
array is [73][356]

I'll be back shortly.  Sorry for the rush.
Avatar of mf55

ASKER

it's ok,
thank you soooo much for you time.
im gonna try fixing it, i'll let u know what happened...
I spent a little time looking at this and ran into a couple of issues.
1)  for (x=0; x < WIDTH; x++)
      }
      }{
     had me confused on the braces, so I changed the code there.
2)  for (y=0; y < HEIGHT; y++)
      {
         if (array[y][x] == 1 )
            c1++;
         else
            c0++;
      }
      re-uses the "y" from the enclosing loop, which naturally clobbers the outer loop.

I'm pasting my modified code in below.  See comments beginning with "josgood".  I cheated a little bit, since I don't have pic.h.

It is now my bedtime (have work tomorrow) so this is my last post for today.  This seems to run for me.  Check out the differences between your version and mine and hopefully they will lead you to the solution.

Cheers!

//#include <pic.h> // josgood hack
#include <stdio.h>

#define RHEIGHT 292
#define HEIGHT 73
#define WIDTH 356

int aData [WIDTH];
TRISD=0xFF;      //initialize port B as Input
TRISC=0x00; //initialize port D as an output
const int PORTD = 0; // josgood hack
int pin=0; // PORTD; // decimal // josgood hack
/*
      mark = 1 --- nothing all black
      mark = 2 --- right light
      mark = 3 --- left light
      mark = 4 --- normal
      mark = 5 --- line right in the middle

      0 represents black
      1 represents white
*/

int dataAnalyze (void)
{
   int x, mark = 0;
   int leftCount = 0;
   int rightCount = 0;
   int result;

   for (x = 0; x < WIDTH; x++)
   {
      /*
        first value is a 0 so there is a possibility of all of them being 0
        so we set mark as 1
      */
      if ( aData[x] == 0 )
      {
         mark = 1;
         leftCount++;
         /* set left counter, in case of a situation where 0011000
            in where we would need to keep track of the 0's on the left and right
            in order to know which light should go off */
         continue;
      }
      else
      {
         /* in this block 1 has gone of for the first time */
         if ( mark == 1 )
            mark = 2; // since there was 0's before the right side has been set so the right light should go off in this scenario
         else
            mark = 3; // otherwise no 0's were gone of in the first time so left is a possibility
         x = x + 1;
         for (x; x < WIDTH; x++)
         {
            if ( aData[x] == 0 )// here a 0 goes off so scenario is at 00001100
            {
               rightCount++;      // need to keep track of the 0s on the right side
               x = x + 1;
               for (x; x < WIDTH; x++)
               {
                  rightCount++;
                  if ( aData[x] == 1 ) // a 1 has gone of so scenario is at 10001 or 0111101 so that means we got a perfect scenario
                  {
                     mark = 4;
                     break;
                  }
               }
            }
     
            if (mark == 4)
               break;
         }
      }

      if ( mark == 4 )
         break;
   }
   if (mark == 2) // here the count values are checked to determine if left should go off or right
   {
      if (leftCount < rightCount)
         mark = 3;
      else if (leftCount == rightCount)
         mark = 5;
   }

   return mark; // return the value
}

void main (void)
{      
   /* variable declaration */
   int pin=0;
   int array[RHEIGHT][WIDTH]; // josgood change first subscript
   int c1, c0;
   int line_check, x, y;
   int y2; // josgood
   int c, result;
                 
   while (1)
   {
      for (y=0; y < RHEIGHT; y++) //292
      {
         line_check = y%4; //checks 4 lines
         if (line_check == 0)
         {
            for (x=0; x < WIDTH; x++)
// josgood comment out this line                                          }
// josgood comment out this line            }{
            {
               if ( pin > 60 )
                  array[y][x] = 1; // repersents white
               else
                  array[y][x] = 0;      //represents black
            }

            /* makes a single array of width 356 with 1/0s to rep white or black for analyzation*/

            for (x = 0; x < WIDTH; x++)
            {
               c1 = 0;
               c0 = 0;
               for (y2=0; y2 < HEIGHT; y2++) // josgood change to y2
               {
                  if (array[y2][x] == 1 ) // josgood change to y2
                     c1++;
                  else
                     c0++;
               }
               if (c1 > c0)
                  aData[x] = 1;
               else
                  aData[x] = 0;
            }
           
            /* result stored array */
            result = dataAnalyze();
             
            if (result == 0)
                  printf ("0");
            else if (result == 1)
                  printf ("1");
            else if (result == 2)
                  printf ("2");
            else if (result == 3)
                  printf ("3");
            else if (result == 4)
                  printf ("4");
            else
                  printf ("5");
         } // josgood Added this line
      }
   } // josgood Added this line
}


How are things going for you?
Avatar of mf55

ASKER

Getting more and more confused but you are extremely helpful! The pic i'm using can't store the data!!!! So I'm trying to use the RFC Robot Controller...... Again, I have my code but can't seem to figure out how to compile it to put it in the controller......... IF you have any idea about this it would be amazing. I know I have to use MPLAB but then in project wizard, I can't figure out what microcontroller to use!
Thank you.

>>>The pic i'm using can't store the data
As I recall, I had to do two steps:
1)  Compile and link the program
2)  Download the program to the PIC
The microchip page
     http://www.microchipc.com
has quite a bit of help.  One item there is a serial port bootloader (for downloading your code to the PIC) for the 16F877A.  That should help.  If I recall correctly, the PIC usually comes with a serial bootloader already installed -- I may be wrong there.  At any rate, I believe the serial port is your solution.

I Googled for MPLAB and found several links -- I suggest you try that.  One page leads to MicroChip's description of MPLAB and that page leads to a list of Webinars -- one of which is titled "ips and Tricks Using MPLAB v6.61".

My experience is a bit elderly now, so I think the best advice I can offer here is to Google around.
Avatar of mf55

ASKER

i've googled as much as possible, but nothing is being helpful. I changed the PIC that im using to PIC18F452, i thought it has more memory(which it does) but for some reson it still giving me memory problems because of the width of the line im using. im storing the width in an array I[WIDTH].if i lower the width, the code compiles perfect on MPLAB IDE.but once i put the actual width of my image, the memry is getting full and it cant compile it.i have the PIC programmer and i know how to use it, but i cant build the code for me to put it in my PIC.
im gonna show you the new algorithm im using, if u can please tell me if im storing my information in a wrong way or if im doing anything wrong that is taking up all the memory on my PIC.
i have another question about that code, if u see im assigning the value of port D to a variable p   'p=PORTD'  and i have that in a loop so it keeps getting the new values of port D. the value of port D is being stored in an array I[WIDTH]. my question is, once that array is full and processed will it get new values from port D???or do i have to put the whole code in a loop in order for it to do that???
here is the code:

#include <stdio.h>
#include <p18f452.h>
#define WIDTH 55

int DetectLines(int *I);

void main (void)
{
      int p = 0, i = 0, z = 0, result = 0;
      int I[WIDTH];

      TRISD=0xFF;
      TRISB=0x00;
    while (1)
    {
      p = PORTB;

      for (i = 0; i < WIDTH; i++)
      {
            I[i] = p;
      }
      for (z = 0; z < WIDTH; z++)
      {
         if (p > 80)
         {
               I[z] = 1;  // Representing white
         }
         else
         {
               I[z] = 0; // Representing black
         }
      }
    }

      result = DetectLines(I);
}



int DetectLines(int *I)
{
      /*
      result = 0 --- nothing all black
      result = 1 --- left light
      result = 2 --- right light
      result = 3 --- normal

      0 represents black
      1 represents white
*/
      int x = 0, y = 0;
      int ctr = 0;// Used to count how many white trailing white lines
      int lastBit = 0;// Used to know the value of the last checked pixel
      int edgeWidth = 7;// Defines the width of an edge, the value can be changed depending on the typical edge width that the camera gives us
      int result = 0;
      lastBit = I[0];

      for(x = 1; x < WIDTH; x++)
      {
            if(I[x] == 1 && lastBit == 1)
            {
                  ctr++;
            }
            else if(I[x] == 0 && lastBit == 1)
            {
                  if(ctr >= edgeWidth)// this means we have an edge
                  {
                        if( x < WIDTH/2)// we detected an edge in the first half
                        {
                              result = 1;
                        }
                        else // We detected an edge in the second half of the image
                        {
                              if(result == 1)
                              {
                                    return 2;
                              }
                              else
                              {
                                    return 3;
                              }
                        }
                  }

                  ctr = 0;
            }

            lastBit = I[x];
      }

      return result;
if (result==0)
      {
      PORTB=5;
      }
else if (result==1)
      {
      PORTB=4;
      }
else if (result==2)
      {
      PORTB=2;
      }
else
      {
      PORTB=0;
      }
      
}





Avatar of mf55

ASKER

by the way, the actual width of the image is 356 but i have it 55 in order for the code to compile...
I'll look at this in 3-4 hours -- I'm at work so have to do some work things.  Sorry about the delay.
>>>doing anything wrong that is taking up all the memory
I sure don't see anything.  You have a singly-subscripted array that is 55 or 356 ints in size -- that can't be a problem.  It's allocated once and lives for the life of the program, so there's no issue like repeated allocations using up memory.  Besides an issue like that is a run-time issue, not a compile-time issue.

You might try moving
      int I[WIDTH];
outside of main().  I'm just guessing here...thinking that perhaps changing from an automatic allocation to a static one might help.  Frankly, I'm baffled.

>>>once that array is full and processed will it get new values from port D?

It should get new values from the port, just the way it is written.

I see a pair of issues with Main()
1)  The loop
      for (i = 0; i < WIDTH; i++)
      {
            I[i] = p;
      }
ends up being without use because the next loop overwrites the entire I[] with either 0 or 1.  I can't tell what is intended here -- but something isn't right.

2)  DetectLines never gets called because it is outside the
    while (1)
    {
    ....
    }

Those issues need to be fixed before we can tell what is going on.
 
Sorry, hit submit accidentally.  The second issue needs to be fixed for sure.  The first one has no effect.
Avatar of mf55

ASKER

Hello,
just a quick one(not long like the others:) any idea how to store an input in the RAM of a PIC18F452???
because it seems like i wont be able to process the data right away.
Thank you.
ASKER CERTIFIED SOLUTION
Avatar of josgood
josgood
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hello
I'm having trouble using the sensor OV6620, I know the camera C3088.
I am using a PIC24F64GA128 to process images, but can not connect the camera to the microcontroller.
I saw that is using Pic16F877A, I wish that I send the codes and schematic for connection so that I can find what is wrong in my project.
I have several documents, datasheets, codes, we can exchange experiences.
If you can please send me some material, I am stating.
Thank you very much
Luciano Henrique Albano
ice_luck@hotmail.com (email and MSN)