Sunday, May 19, 2013

Taking Pictures with a pcDuino & a LinkSprite JPEG Color Camera (TTL Interface)

Here is a very basic example showing how to use the LinkSprite JPEG Color Camera (TTL Interface) from Sparkfun with a pcDuino.

The user manual for the camera is available here.

Note (May 24, 2013): I have also gotten a TTL Serial JPEG Camera with NTSC Video from Adafruit. It is the same camera as the Linksprite Sparkfun (with some minor differences in the board and the connector).  The material presented below also works with the Adafruit camera. Adafruit Learning systems has a tutorial on using the camera with an Arduino and a utility for testing the camera.  They also have code on their GitHub site that includes some python examples apparently intended for the Raspberry Pi.

Connections


The labels for the connections on the camera board are just above the connector.

Camera pcDuino
TV     Not Connected
RXD    Digital Pin 1 (TX)
TXD    Digital Pin 0 (RX)
GND    GND
VCC    5V

Note: If you have problems with getting serial I/O to work on the pcDuino's 0 and 1 pins, try the setuart2 utility discussed in the pcDuino forum.

Python Code


The following code is designed to be run from the command line on the pcDuino. It just takes a picture and saves it to a file in the /tmp/ directory. The file name is made up of the current date and time (down to seconds).   

import serial
import time
import datetime

# Initialize camera
serial = serial.Serial("/dev/ttyS1", baudrate=38400)
serial.write(b'\x56\x00\x26\x00')
resp = ""
time.sleep(1)
while (serial.inWaiting() > 0):
        data = serial.read()
        resp += data
        if "Init end\r\n" in resp:
                print "Ready"
                break

# Take picture
serial.write(b'\x56\x00\x36\x01\x00')
resp = ""
time.sleep(2)
while (serial.inWaiting() > 0):
        data = serial.read()
        resp += data
        if b'\x76\x00\x36\x00\x00' in resp:
                print "Picture taken"
                break

#Get JPG size
serial.write(b'\x56\x00\x34\x01\x00')
resp = ""
time.sleep(1)
while (serial.inWaiting() > 0):
        data = serial.read()
        resp += data
        if b'\x76\x00\x34\x00\x04\x00\x00' in resp:
                msb = serial.read()
                lsb = serial.read()
                print "Image file size: %d bytes" % (ord(msb) << 8 | ord(lsb))

# Write image to file
serial.write(b'\x56\x00\x32\x0C\x00\x0A\x00\x00\x00\x00\x00\x00%c%c\x00\x0A' % (msb,lsb))
time.sleep(3)
now = datetime.datetime.now()
filename = "%d.%02d.%02d.%02d.%02d.%02d.jpg" % \
        (now.year,now.month,now.day,now.hour,now.minute,now.second)
resp = serial.read(size=5)
if b'\x76\x00\x32\x00\x00' in resp:
        with open("/tmp/" + filename, 'wb') as f:
                while (serial.inWaiting() > 0):
                        data = serial.read()
                        f.write('%c' % data)
        print "Image written to /tmp/%s" % (filename)


If you are interested in changing the image size, see this post

12 comments:

  1. Hi Brad,
    Tried to run both code possibilities but I got the following:

    ubuntu@ubuntu:~/Desktop$ python cam.py
    Traceback (most recent call last):
    File "cam.py", line 53, in
    serial.write(b'\x56\x00\x32\x0C\x00\x0A\x00\x00\x00\x00\x00\x00%c%c\x00\x0A' % (msb,lsb))
    NameError: name 'msb' is not defined

    and than


    ubuntu@ubuntu:~/Desktop$ python cam2.py
    Traceback (most recent call last):
    File "cam2.py", line 41, in
    serial.write(b'\x56\x00\x32\x0C\x00\x0A\x00\x00\x00\x00\x00\x00%c%c\x00\x0A' % (msb,lsb))
    NameError: name 'msb' is not defined

    Can you help me out to understand what am I doing wrong?
    Thx

    ReplyDelete
    Replies
    1. Hi Filipe -

      Does the line print "Image file size: %d bytes" % (ord(msb) << 8 | ord(lsb)) produce a reasonable number? You might also print out he value of msb after the line msb = serial.read(). I wonder if the response to the image size query is coming back wrong? Let me know what you find.

      Delete
  2. Hi Brad,

    Thanks for the prompt reply. I've downloaded the file using Mac for a text file... brought it to pcduino... run it and got the follow:


    ubuntu@ubuntu:~$ cd Desktop
    ubuntu@ubuntu:~/Desktop$ python cam.py
    File "cam.py", line 22
    SyntaxError: Non-ASCII character '\xc2' in file cam.py on line 22, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

    If I do it directly on pcduino (copy the code from your website to leafpad&save it ccc.py), got the following:

    ubuntu@ubuntu:~/Desktop$ python ccc.py
    Traceback (most recent call last):
    File "ccc.py", line 41, in
    serial.write(b'\x56\x00\x32\x0C\x00\x0A\x00\x00\x00\x00\x00\x00%c%c\x00\x0A' % (msb,lsb))
    NameError: name 'msb' is not defined
    ubuntu@ubuntu:~/Desktop$

    what do you think?

    Filipe

    ReplyDelete
    Replies
    1. Hi Filipe -

      It seems that you may have a text encoding problem that is confusing the Python interpreter.

      When I work with my pcDuinos, I normally connect using SSH (over my local network). I do my editing on the pcDuino using nano or vi (from the Linaro/Ubuntu command line). Windows 7 and 8 are my main desktop OSes, but I find that using SSH in a terminal window on my Mac has the same results. I've copied and pasted the code above into new files using nano or vi several times and it keeps working for me. I never use the graphical desktop on the pcDuino, but I should give it a try to see if I can reproduce the problems you're running into.

      If you use SSH to access your pcDuino and edit with vi or nano, can you get it to work? Nano is easier to use than vi, and you can install it by running the command apt-get install nano.

      --Brad

      Delete
    2. Hi Filipe -

      I have tried the code above on a second pcDuino and find that it errors out with the msb not defined error message you've been getting..

      When I run uname -a on the pcDuino where the code works, it reports

      Linux ubuntu 3.4.29+ #3 PREEMPT Wed Apr 3 17:17:59 CST 2013 armv7l

      The pcDuino where the code does not work says

      Linux ubuntu 3.4.29+ #1 PREEMPT Tue Apr 2 01:32:53 CST 2013 armv7l

      Both have Python ver. 2.7, so something else must be the cause of the difference. I bought the boards from the same vendor (Sparkfun) but at different times. Maybe I'll need to re-image the one that doesn't work...

      --Brad

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi Brad,

    Good idea. It would be interesting if you could try using pcduino graphical interface to copy the code... if one would get the same outcome...

    I've copied the code (from Mac) and than into nano (in pcduino enviroment) and saved as cam.py.
    When I run it at the terminal it says:

    ubuntu@ubuntu:~/Desktop$ python cam.py
    File "cam.py", line 12
    SyntaxError: Non-ASCII character '\xc2' in file caca.py on line 12, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

    I'll try out your suggestion with SSH. Let you know in the coming days...

    Interesting results and perspective... I was recently reading that there are several updated versions...I've created a bootable SD using 20130531 Ubuntu image (which needs 300 upgrades) and winwriter. Which one are you using? Also SD bootable?

    - Filipe

    ReplyDelete
    Replies
    1. Hi Filipe -

      Last May in a post about using a serial RFID reader with the pcDuino, I mentioned something about the serial port that I had forgotten in the meantime:

      If you have problems with getting serial I/O to work on the pcDuino's 0 and 1, try the setuart2 utility discussed in the pcDuino forum. (the post with the actual links is at http://bradsmc.blogspot.com/2013/05/rfid-for-pcduino-using-innovations-id12.html).

      The non-ASCII character error looks like an encoding issue, but the "msb not defined" error also comes up if the pcDuino can't communicate with the camera (my code example has almost no error handling, so it only tells when things work, not when they fail). I don't remember if I made changes to my pcDuino's serial port or not. I haven't reflashed the OS and don't normally boot from SD, so I just use apt-get update/upgrade to keep things current. I'll try the serial port fix on my board where the code doesn't run correctly and see if it helps.

      --Brad

      Delete
    2. Hi Filipe -

      I just tried the setuart2 program (mentioned in my previous response) on the pcDuino that didn't work. It has now resolved the serial port issue so that the Python script can access the camera.

      You may still have some sort of character encoding issue, but the "msb not defined" error should be taken care of by setuart 2.

      --Brad

      Delete
  5. Very usefull tutorial. We forward your post to learn.linksprite.com. If you have any other new post about pcDuino(www.pcduino.com) or any other LinkSprite's(www.linksprite.com) products, please feel free to let us know. If you have a new post, could you please give us a backlink?

    ReplyDelete
  6. while reading the jpeg file content, it was mentioned there will be interval time delay between 76 00 32 00 00, and FF d8. Could I know how I can wait in the code (if I am implementing code using C) for interval time.

    Second doubt is could I know what serial.inWaiting() is doing. thanks..

    ReplyDelete
    Replies
    1. Hi Chaitanya -

      I haven't had time lately for pcDuino programming, so I haven't tried it, but I think you should be able to use sleep() with a value in seconds or usleep() for a delay measured in milliseconds in C.

      The inWaiting() method in the Python code above returns the number of characters waiting in the receive buffer.

      Delete