Here is a new version of the viewer program.
It shows crude grayscale at the top and the "U" and "V" channels at the bottom.
Try holding different solid color object to the camera and see the "U" and "V" results.
Red has a "light" affect on the "V" channel.
Blue has a "light" affect on the "U" channel AND a "dark" affect on the "V" channel.
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
tiles = vga#xtiles * vga#ytiles
tiles32 = tiles * 32
SerRxPin = 0 ' Serial interface connect to Sout on LRF
SerTxPin = 1 ' connect to Sin on LRF
OBJ
vga : "vga_512x384_bitmap"
ser : "JDCogSerial" ' Full-duplex serial communication (Carl Jacobs, http://obex.parallax.com/objects/398/)
VAR
long sync, pixels[tiles32]
word colors[tiles]
PUB start | h, i, j, k, x, y, value
ser.Start(|<SerRxPin, |<SerTxPin, 19200) ' Start JDCogSerial cog
'start vga
vga.start(16, @colors, @pixels, @sync)
'init colors
repeat i from 0 to tiles - 1
colors[i] := $FC00 ' White on black
waitcnt(cnt+clkfreq)
ser.Tx("U")
waitcnt(cnt+clkfreq)
repeat
waitcnt(cnt+clkfreq/4)
ser.RxFlush
ser.Tx("Y")
y := 0
repeat 80
x := 0
repeat 64
value := ser.Rx ' Read Y1
plotGS(x, y, value)
value := ser.Rx ' Read U
plotGS(x>>1, y+170, value)
value := ser.Rx ' Read Y2
plotGS(x+2, y, value)
value := ser.Rx ' Read V
plotGS(x>>1+138, y+170, value)
x += 4
y += 2
PRI plotGS(x, y, value)
if value > 51
plot(x, y)
else
unplot(x, y)
if value > 102
plot(x+1, y+1)
else
unplot(x+1, y+1)
if value > 153
plot(x+1, y)
else
unplot(x+1, y)
if value > 204
plot(x, y+1)
else
unplot(x, y+1)
PRI plot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
PRI UnPlot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
pixels[y << 4 + x >> 5] ^= |< x
I know this picture isn't very good but your viewer works for me using your firmware. At first I thought it did just a frame grab until I stood in front of the LRF and found out it is constantly updating.
Dave,
Nice. If you hold up a large blue object you should see a pattern in the U and V fields.
I am working on a new version that will capture a frame and then let the remote request the data one line at a time. This will allow you to communicate much faster by using a buffer to store 1 line, process it, then request another line. The lines can be requested in any order. So you can just request the line you are interested in. Requesting a line > 79 terminates the command.
I'd also like to allow the single line data to be returned in RGB format (16-bit or 24-bit). I'm working on that part now.
Talk about a fancy line scanner! I thought I would post some pixs I took of the uOLED and the view the LRF was looking at. That device is so small it was hard to get a good picture. Also a pix of my current setup.
Dave,
Here is the latest version that returns lines in RGB (8-bits each, 384 bytes per line).
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
tiles = vga#xtiles * vga#ytiles
tiles32 = tiles * 32
SerRxPin = 0 ' Serial interface connect to Sout on LRF
SerTxPin = 1 ' connect to Sin on LRF
OBJ
vga : "vga_512x384_bitmap"
ser : "JDCogSerial" ' Full-duplex serial communication (Carl Jacobs, http://obex.parallax.com/objects/398/)
VAR
long sync, pixels[tiles32]
word colors[tiles]
byte cameraline[128*3]
PUB start | x, y, i, value, lineNo
ser.Start(|<SerRxPin, |<SerTxPin, 115200) ' Start JDCogSerial cog
'start vga
vga.start(16, @colors, @pixels, @sync)
'init colors
repeat i from 0 to tiles - 1
colors[i] := $FC00 ' White on black
waitcnt(cnt+clkfreq)
ser.Tx("U")
waitcnt(cnt+clkfreq)
repeat
ser.Tx("Z")
y := 0
repeat lineNo from 0 to 79
ser.rxFlush
ser.Tx(lineNo)
repeat i from 0 to 383
cameraLine[i]:=ser.Rx
x := 0
i := 0
repeat 128 ' 128 pixels per line
value := cameraLine[i++] ' Read r
plotGS(x, y, value)
value := cameraLine[i++] ' Read g
plotGS(x+256, y, value)
value := cameraLine[i++] ' Read b
plotGS(x+128, y+170, value)
x += 2
y += 2
ser.Tx(255)
PRI plotGS(x, y, value)
if value > 51
plot(x, y)
else
unplot(x, y)
if value > 102
plot(x+1, y+1)
else
unplot(x+1, y+1)
if value > 153
plot(x+1, y)
else
unplot(x+1, y)
if value > 204
plot(x, y+1)
else
unplot(x, y+1)
PRI plot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
PRI UnPlot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
pixels[y << 4 + x >> 5] ^= |< x
I couldn't get a good picture of the uOLED but heres a color pix on uOLED and a normal shot of the room as the lrf would see it. There is a dark colored bookcase on the right hand side that probably should be dark or black show blue on the uOLED. But other than that everything else looks natural.
Con
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
ack = $06 ' Acknowledge byte
nak = $15 ' Invalid command byte
Var
byte cameraline[128*3]
Obj
db : "pcfullduplexserial"
fd : "fullduplexserial"
Pub start| i,j,x,y
fd.start(6, 7, 0, 115200) '
db.init
db.addport(0, 31, 30, -1, -1, 0, 0, 19200) 'debug port
db.addport(1, 4, 5, -1, -1, 0, 0, 115200) 'uoled
db.start
waitcnt(clkfreq*3+cnt)
fd.rxflush
fd.tx("U")
repeat until fd.rx == ":"
db.str(0, string("Camara online",13))
db.rxflush(1)
db.tx (1, "U")
waitack
db.str(0, string("uOLED ready",13))
waitcnt(1600000+cnt)
erase
repeat
get
Pub waitack
repeat until db.rx(1) == ack
Pub erase
db.tx (1, "E")
waitack
Pub get | i, r, g, b, x, y, z
fd.tx("Z")
repeat y from 0 to 79
fd.rxflush
fd.tx(y)
repeat i from 0 to 383
cameraline[i]:=fd.Rx
i := 0
repeat x from 0 to 127
r := cameraline[i++]
g := cameraline[i++]
b := cameraline[i++]
plot(x, y, r, g, b)
Pub plot(x, y, r, g, b)
' X : 0 to 127
' Y : 0 to 127
' Red : 0 to 255
' Green : 0 to 255
' Blue : 0 to 255
r := r >> 3 << 11 | (g >> 2 << 5) | (b >> 3)
db.tx(1, "P")
db.tx(1, x)
db.tx(1, y)
db.tx(1, r.byte[1])
db.tx(1, r.byte[0])
waitack
Dave, Yeah I can't really see anything in the picture.
By "everything else looks natural" you mean the image color look good ?
I've noticed that sometimes black shows blocks of white (full on), but I have the variables limited so I can't tell why it does that sometimes. That may be the blue you are seeing instead of black.
Try to get a better picture of the oLED if you can. I'd love to see a color image.
Dave,
Here is a version of the viewer that shows color objects.
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
tiles = vga#xtiles * vga#ytiles
tiles32 = tiles * 32
SerRxPin = 0 ' Serial interface connect to Sout on LRF
SerTxPin = 1 ' connect to Sin on LRF
OBJ
vga : "vga_512x384_bitmap"
ser : "JDCogSerial" ' Full-duplex serial communication (Carl Jacobs, http://obex.parallax.com/objects/398/)
VAR
long sync, pixels[tiles32]
word colors[tiles]
byte cameraline[128*3]
PUB start | x, y, i, r, g, b, lineNo
ser.Start(|<SerRxPin, |<SerTxPin, 115200) ' Start JDCogSerial cog
'start vga
vga.start(16, @colors, @pixels, @sync)
'init colors
repeat i from 0 to 6*16
if i & 15 < 8
colors[i] := 3<<14 ' red
else
colors[i] := 3<<12 ' green
repeat i from 5*16 to 12*16-1
colors[i] := 3<<10 ' Blue
waitcnt(cnt+clkfreq)
ser.Tx("U")
waitcnt(cnt+clkfreq)
repeat
ser.Tx("Z")
y := 0
repeat lineNo from 0 to 79
ser.rxFlush
ser.Tx(lineNo)
repeat i from 0 to 383
cameraLine[i]:=ser.Rx
x := 0
i := 0
repeat 128 ' 128 pixels per line
r := cameraLine[i++] ' Read r
g := cameraLine[i++] ' Read g
b := cameraLine[i++] ' Read b
' Only show the strongest color
if (r > g) and (r > b)
plotGS(x, y, r)
else
plotGS(x, y, 0) ' Plot R
if (g > r) and (g > b)
plotGS(x+256, y, g) ' Plot G
else
plotGS(x+256, y, 0)
if (b > r) and (b > g)
plotGS(x+128, y+170, b) ' Plot B
else
plotGS(x+128, y+170, 0)
x += 2
y += 2
ser.Tx(255)
PRI plotGS(x, y, value)
if value > 51
plot(x, y)
else
unplot(x, y)
if value > 102
plot(x+1, y+1)
else
unplot(x+1, y+1)
if value > 153
plot(x+1, y)
else
unplot(x+1, y)
if value > 204
plot(x, y+1)
else
unplot(x, y+1)
PRI plot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
PRI UnPlot(x,y)
' if x => 0 and x < 512 and y => 0 and y < 384
pixels[y << 4 + x >> 5] |= |< x
pixels[y << 4 + x >> 5] ^= |< x
Bean I finally burned out my uOLED last night. This was my second one and I knew about their problems of removing power before issueing a power down command. I had taken many pictures of the uOLED but that was the best one. Looking at it in person except for the blue everything else in the picture the color tones looked as they did in real life. When I turned the LRF to a spot with no dark places in it the whole picture looked natural. I also have a C328 camera so I will be looking for another serial color display device without the problem posted below. Have any suggestions?
Good grief! Software (or the lack thereof) should never be allowed to damage the hardware that it drives. Would it have been so hard for the uOLED designers to include an automatic power-down sequencer? Hewlett Packard discovered this the hard way on their HP85 desktop computer that had a built-in thermal printer. Problem was, the thermal printhead was controlled in software by the main microprocessor. A bug in the user's software could cause the printhead to overheat and burn out, since there was no hardware one-shot to limit the "on" time.
Good grief! Software (or the lack thereof) should never be allowed to damage the hardware that it drives. -Phil
Agreed. HOWEVER, one of my back burner projects is just to make an LED clock. Dull and boring, but I want to do the LED multiplexing directly using my 16 little IO pins. A good challenge. Trouble is, the duty cycle is so low (like 1/24) that I have to overdrive each LED segment just to make it bright enough to see. Which means driving the LED segment directly (and briefly) from the IO pin's 5V with no resistor. No problem as long as the program keeps running. But if & when the program stops execution (code error? Moi?) during development, I'm likely to release the magic smoke from the IO pin. Oh sure, I could use an optoisolator buffer for protection, but where's the fun in that?
I am trying right now to communicate between RobotBasic and the LRF. RobotBasic has bit mapped graphics and serial communication on the computer so it may take me a while to see if I can do it that way.
The new LCD Parallax sells should display a 8 bit grey scale image from the camera on the laser range finder.using this program. I have a different model than Parallax's but it is the same type. So anybody that happens to have both give this a try. Bean I am using the original firmware's "G" command and it puts out 160 x 128 not 176 x 144 as it describes for GR_X and GR_Y. I might have to take a look again at your firmware and see if I can attain color results.
Edit: The LCD display uses RGB565 but this program converts the 8bit grey scale from the camera to the LCD's RGB565.
Con 'display picture from Parallax laser range finder to 4D systems ulcd
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
ACK = 6
LCD_RX = 17 'input from lcd transmit pin
LCD_TX = 16 'output to lcd receive pin
LRF_RX = 15 'input from laser range finder transmit pin
LRF_TX = 14 'output to laser range finder receive pin
Var
byte buffer[20480]
Obj
lcd : "fullduplexserial"
lrf : "fullduplexserialplus"
Pub Main
lcd.start(LCD_RX, LCD_TX, 0, 115200)
lrf.start(LRF_RX, LRF_TX, 0, 115200)
lrf.tx("U")
repeat until lrf.rx == ":"
lcd.tx($ff)
lcd.tx($cd)
get_ack
display_frame
Pub Get_Ack
if lcd.rxtime(1000) == ACK
return true
else
return false
Pub Display_Frame | i, r, g, b, x, y
lrf.rxflush
lrf.tx("G")
i := 0
repeat
buffer[i++] := lrf.rx
if i > 20480
waitcnt(350000 + cnt)
lrf.rxflush
quit
i := 0
lcd.rxflush
repeat y from 0 to 127
repeat x from 0 to 159
r := g := b := buffer[i++]
put_pixel(x, y, r, g, b)
Pub Put_Pixel(x, y, r, g, b) | color
color := r >> 3 << 11 | g >> 2 << 5 | b >> 3
lcd.tx($ff)
lcd.tx($c1)
lcd.tx(x >> 8)
lcd.tx(x)
lcd.tx(y >> 8)
lcd.tx(y)
lcd.tx(color >> 8)
lcd.tx(color)
get_ack
Here is a slightly improved version. Got rid of not needed stuff but this version takes 30 seconds to completely display a picture from the time you hit F10. That's because this version sets up the camera for it's current environment (white balance etc). It does
print the picture faster to the screen as it ignores the ACK's for the Put_Pixel method. I believe the first version if you comment out the get_ack in the Put_Pixel method you can get a picture to print in less than 20 seconds but you have to take a couple of
pictures in a row to get the white balance etc.setup. This also prints a message to the screen asking you to wait.
Con 'display picture from Parallax laser range finder to 4D systems ulcd
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
ACK = 6
LCD_RX = 17 'input from lcd transmit pin
LCD_TX = 16 'output to lcd receive pin
LRF_RX = 15 'input from laser range finder transmit pin
LRF_TX = 14 'output to laser range finder receive pin
Var
byte buffer[20480]
Obj
lcd : "fullduplexserial"
lrf : "fullduplexserialplus"
Pub Main
lcd.start(LCD_RX, LCD_TX, 0, 115200)
lrf.start(LRF_RX, LRF_TX, 0, 115200)
clear_screen
put_string(@splash)
lrf.tx("U")
repeat until lrf.rx == ":"
lrf.tx("E")
repeat until lrf.rx == ":"
clear_screen
display_frame
Pub Clear_Screen
lcd.tx($ff)
lcd.tx($cd)
repeat until lcd.rx == ACK
Pub Display_Frame | i, r, g, b, x, y
lrf.tx("G")
i := 0
repeat
buffer[i++] := lrf.rx
if i > 20480
repeat until lrf.rx == ":"
quit
i := 0
repeat y from 0 to 127
repeat x from 0 to 159
r := g := b := buffer[i++]
put_pixel(x, y, r, g, b)
waitcnt(clkfreq/100 + cnt)
lcd.rxflush
Pub Put_Pixel(x, y, r, g, b) | color
color := r >> 3 << 11 | g >> 2 << 5 | b >> 3
lcd.tx($ff)
lcd.tx($c1)
lcd.tx(x >> 8)
lcd.tx(x)
lcd.tx(y >> 8)
lcd.tx(y)
lcd.tx(color >> 8)
lcd.tx(color)
Pub Put_String(str)
lcd.tx($00)
lcd.tx($18)
lcd.str(str)
lcd.tx($00)
repeat until lcd.rx == ACK
Dat
Splash byte "Please wait for camera to",13,10,13,10," setup & take picture",0
Comments
It shows crude grayscale at the top and the "U" and "V" channels at the bottom.
Try holding different solid color object to the camera and see the "U" and "V" results.
Red has a "light" affect on the "V" channel.
Blue has a "light" affect on the "U" channel AND a "dark" affect on the "V" channel.
Bean
Nice. If you hold up a large blue object you should see a pattern in the U and V fields.
I am working on a new version that will capture a frame and then let the remote request the data one line at a time. This will allow you to communicate much faster by using a buffer to store 1 line, process it, then request another line. The lines can be requested in any order. So you can just request the line you are interested in. Requesting a line > 79 terminates the command.
I'd also like to allow the single line data to be returned in RGB format (16-bit or 24-bit). I'm working on that part now.
Bean
Here is the latest version that returns lines in RGB (8-bits each, 384 bytes per line).
Bean
Bean
By "everything else looks natural" you mean the image color look good ?
I've noticed that sometimes black shows blocks of white (full on), but I have the variables limited so I can't tell why it does that sometimes. That may be the blue you are seeing instead of black.
Try to get a better picture of the oLED if you can. I'd love to see a color image.
Bean
Here is a version of the viewer that shows color objects.
Bean
-Phil
Bean
Agreed. HOWEVER, one of my back burner projects is just to make an LED clock. Dull and boring, but I want to do the LED multiplexing directly using my 16 little IO pins. A good challenge. Trouble is, the duty cycle is so low (like 1/24) that I have to overdrive each LED segment just to make it bright enough to see. Which means driving the LED segment directly (and briefly) from the IO pin's 5V with no resistor. No problem as long as the program keeps running. But if & when the program stops execution (code error? Moi?) during development, I'm likely to release the magic smoke from the IO pin. Oh sure, I could use an optoisolator buffer for protection, but where's the fun in that?
Edit: The LCD display uses RGB565 but this program converts the 8bit grey scale from the camera to the LCD's RGB565.
print the picture faster to the screen as it ignores the ACK's for the Put_Pixel method. I believe the first version if you comment out the get_ack in the Put_Pixel method you can get a picture to print in less than 20 seconds but you have to take a couple of
pictures in a row to get the white balance etc.setup. This also prints a message to the screen asking you to wait.