Page 1 of 1

Sorry guys, another question about rangefinding

PostPosted: Sun Aug 13, 2006 8:48 pm
by davedave
I want to use the brightest pixel method, we don't have the ram for a full dump of even just the red pixels so it has to be done as the lines are read.

I need to be able to do a check as the pixels are being read which means either 6 or 14 clock cycles (dumping or tracking mode, -2 cycles for loop), preferably 6 to allow full resolution. I'm thinking of storing a timer1 read as the location in register X and the value in register Z (if memory serves register Y is being used already). Even so, I'm having trouble thinking up how I can squeeze it in to the available cycles. Does anyone know how much time there is at the end of a line read before the next line starts? John has the chip sleeping, but that only guarantees 3 clock cycles. I need there to be enough time to offload my maximum value to an array and still send the chip to sleep (5 clocks).

By only looking at the red pixels I get a whole lot more time but even so it's going to be tight.

PostPosted: Tue Aug 15, 2006 2:22 pm
by Ringo
I'm trying to do the same thing. I was planning on doing it like the DF command. If reads all the data from the camera then sends it out the port later. I was planning on doing the compares at the point where it is sending serial data and then only sending the highest value. I think I'll start by Turning the camera sideways and looking at a row. Right now I'm trying to write a c# app to display the byr data on my screen. Once I get that working I can easily convert it to show my new brightest pixel data. Please post if you get it working.
Ringo

PostPosted: Thu Aug 24, 2006 10:04 pm
by davedave
Yup, modified the screen dump event to only spit out the brightest pixel and displaying the results in matlab. The result is poor at the moment so I'll be implementing a software low pass filter (average) on the data between rows (columns with the camera on its side).

So the modfied code: Receive 'EF' over serial then
1. get dump line
2. pick off red pixels
3. run 3 point averager
4. pick off brightest pixel
5. send brightest pixel over serial
6. repeat till finished

3 and 4 run in one pass, hopefully 2,3,4 in one pass once I get some time.

Here's my modifications and shamless rip off of Johns code with some matlab code including sample data. I haven't put the averager/filter in yet. It should appear as almost a straight line, but obviously doesn't.

function ans = goodData()
% cam holds uncalibrated hexadecimal range data from AVRcam. First byte
% seems to always be bad

% cam2 is similar, but more carefully set up to have a chance at seeing
% side to side
cam = '01 69 69 69 69 69 69 69 69 69 69 67 67 87 87 87 89 67 67 67 67 67 67 65 67 65 65 65 65 65 41 65 65 65 65 65 65 65 65 65 65 65 65 65 63 63 63 63 63 63 63 73 03 05 4D 07 25 07 05 43 73 03 5F 03 2D 09 01 1F 55 01 05 2D';
cam2 = '01 01 01 01 57 43 57 57 57 57 55 55 55 55 55 55 55 55 55 55 55 55 49 55 53 55 03 55 55 53 55 55 55 53 53 53 53 53 53 53 53 53 53 53 51 51 43 51 51 01 23 17 15 51 51 51 4F 51 51 53 53 53 53 1B 2F 51 51 51 4F 4F 4F 4F';
hold on;
m=0;
for n=1:3:(length(cam)-1)
m = m+1;
camN(m)=hex2dec([cam(n),cam(n+1)]);
end
plot(camN,'g');
m=0;
for n=1:3:(length(cam2)-1)
m = m+1;
camN(m)=hex2dec([cam2(n),cam2(n+1)]);
end
plot(camN,'r');
hold off;



Modifications to AVRcam:
Added rangefinding event.
In frameMgr_aquireLine():
if ((currentState == ST_FrameMgr_DumpingFrame)||( currentState == ST_FrameMgr_RF))


In frameMgr_processLine():
else if (currentState == ST_FrameMgr_RF)
{
unsigned char count =0;
unsigned char max =0;
unsigned char place =0;
unsigned char count1 =0;
unsigned char max1 =0;
unsigned char place1 =0;
volatile unsigned char dataToSend1;

/* pick off the largest red value then send it through serial followed
by byte containing magnitude and number of counts at that level (max = 16) */

/* currentLineBuffer is getting "g" previousLineBuffer is getting "b-r" */
//UartInt_txByte(0x0B); /* send the header byte */
//UartInt_txByte(lineCount); /* send the line count */
for (i=0; i<NUM_PIXELS_IN_A_DUMP_LINE; i+=2)
{
/* *previousLineBuffer contains red and blue data*/

place = previousLineBuffer[i];
place &= 0x0F;
if (max < place)
{
count=1;
max = place;
dataToSend = i;
}
if (max==place)
{
count++;
}
place1 = previousLineBuffer[i+1];
place1 &= 0x0F;
if (max1 < place1)
{
count1=1;
max1 = place1;
dataToSend1 = (i+1);
}
if (max1==place1)
{
count1++;
}
}
/* dataToSend should be packed now */

//UartInt_txByte(dataToSend);
//UartInt_txByte((count<<4)|(max&0x0F)); // send count and max as one byte
//UartInt_txByte(max); // send count and max as one byte
//UartInt_txByte(max1);
UartInt_txByte(dataToSend1); // this is the maximum red location
//UartInt_txByte((count1<<4)|(max1&0x0F)); // send count1 and max1 as one byte

//UartInt_txByte(0x0F); /* send line end */
/* once all the data is sent, increment out line count by 2 since
we really get 2 lines worth of pixels on each pass */
/* Update...increment only by 1, but only send 72 double-lines */
lineCount++;

/* check to see if we have retrieved all of the needed lines */
if (lineCount >= 72) /* half 144, since we send two lines at a time */
{
/* we're done, so send the dump complete?...nope, just change
states and we should be fine */
lineCount = 0;
currentState = ST_FrameMgr_idle;

/* disable the PCLK counting overflow interrupt */
TIMSK &= DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK;

CamConfig_setCamReg(0x11,0x00); /* reset the frame rate to normal*/
CamConfig_sendFifoCmds();
}
else
{
/* we have more lines to acquire in this frame, so keep on truckin...*/
PUBLISH_FAST_EVENT(FEV_PROCESS_LINE_COMPLETE);
}
}

Quick update

PostPosted: Sun Aug 27, 2006 11:24 pm
by davedave
The new/revised code works better, still not well. Here it is from frameMgr_processLine

for (i=0; i<(NUM_PIXELS_IN_A_DUMP_LINE+5); i+=2)
{
/* *previousLineBuffer contains red and blue data
known: low nibble of odd addresses = red
theory: low nibble of odd address AND high nibble of even addressed byte in previous line buffer */

place = ((previousLineBuffer[i]>>4)+(previousLineBuffer[i+1]&= 0x0F)+(previousLineBuffer[i+2]>>4));
if (max < place)
{
count=1;
max = place;
dataToSend = i;
}
if (max==place)
{
count++;
}


place1 = ((previousLineBuffer[i+1]&= 0x0F)+(previousLineBuffer[i+2]>>4)+(previousLineBuffer[i+3]&= 0x0F));
if (max1 < place1)
{
count1=1;
max1 = place1;
dataToSend1 = (i+1);
}
if (max1==place1)
{
count1++;
}
}
/* dataToSend should be packed now */

UartInt_txByte(dataToSend);
//UartInt_txByte((count<<4)|(max&0x0F)); // send count and max as one byte
//UartInt_txByte(max); // send count and max as one byte
//UartInt_txByte(max1);
UartInt_txByte(dataToSend1);