Wednesday 24 December 2014

IP Camera

Wednesday 24th December 2014

There are now lots of IP cameras out there, but I'm not impressed, colours are at best 'suspect', Audio out OR Audio in and cheapest is about £30, I think I can do better.

For a development platform I am using Arduino Due, nice fast ARM processor. Bought from Bangood.com for £8.

First I wanted memory card, mmc quite often comes with a free converter, got a few kicking about, got a few 16GB mmc kicking about. I wired 1 of the converters up to Due, few wires, bit of solder, capacitor. Used standard Arduino Cardinfo example software, got it working :-)
Ok, so that was basically free and quick.

Now I discovered ESP8266, ace module, £2 from EBay. Module is 3.3v, Due is 3.3V, wired it up.
Modified code using info off Internet (good old Google).
Needed more power than USB could supply, plugged in a USB mains plug (£1 from Ebay), cured that.
Works rather well, set it up as a web server, 2 pages (config & index), can see both pages on PC and phone browsers, some things I don't understand with requests for favourites icon.
Modified so I can have debug statements over serial to PC or not (DBG flag). Turned off serial.
I now have a stand-alone Wifi web server :-)

rigged up Arduino Due
Programming port goes to PC USB for programming and debug.
Power connector goes to USB main plug.
SDIO block and orange wire connected to SDCard
Brown/blue and green/white twisted pairs go to ESP8266
The rigged up SDCard
The rigged up ESP8266 module

That is current 'state of play', what's next?

I have an Omnivision OV2640 2MP camera module, I now need to rig that up and get it working with the Due, this is a bit more tricky, camera is on a flexi with 25 pins 0.5 mm pitch.
I think I'm going to have to make a PCB for this one.

Basic plan is to get it all running on Due, I'll then know how it all needs to work. Then maybe I can get it all working with ESP8266 acting as main processor (remove the Due). I'll then have a really small, fully functioning IP Camera for around £5.
I'll update this post as I progress.

17-01-2015
PCB was a pain, I got the mmC mirrored, I got the camera mirrored, took me 4 attempts, I only bought 2 1.3V LDO, 1 broke, 1 lost, awaiting delivery. Rest of the PCB is working, pictures:
 

Left is the bare PCB, etched drilled and trimmed. Right is the loaded PCB attached to Due.
Getting there, bit slower than I'd like, but steady.

31-01-2015
This has not been as easy as I hoped.
Latest revision of PCB. Note the Micro Memory Card holder on top right. 3D printed guide in clear PLA. Almost everything is working using an Arduino sketch. Reading and writing happily from mmC, fully active on Wifi with ESP8266, control and see results over standard USB serial, I have a simple web server running on Wifi, I can happily browse on PC or phone. Currently concentrating on camera.
OV2640 is not easy, got datasheet, could not get it running with just that, it seems like you have enough information, but when you try to use it you don't get expected results. Found the OV2640 application note, now a bit clearer, there are lots of register sequences, nearly 90% of them are writes to 'Reserved' registers. But using a recommended sequence and capturing VREF signals via interrupt and incrementing counter, I can see it is streaming. So basic control is running, it is streaming, but I need to capture the frames. Sketch is a mess, not sure Arduino is up to the task.
I tried switching to Atmel Studio 6, struggling to get the easy stuff going. SD card is supported, but not for Due and docs are not got enough to easily modify for Due.
Currently thinking, either crack on with Atmel Studio 6, or back to Arduino and tidy it up by moving the OV2640 into some kind of lib.

Can the Due handle image capture? A lot of data coming dead quick. I'll try with pure interrupts (save byte per PCCLK (Pixel clock) gated with VREF, I was thinking DMA, but I'm not convinced that it can be done, I have heard that GPIO registers are memory mapped, I have data coming in on Port C low byte, so it may be feasible to DMA bytes from single address (Port C) gated by PCCLK to RAM buffer, but I have found no details on setting up DMA on Due or SAM3X in this configuration.
I will crack it.

01/02/2015
Need to expand on 'A lot of data coming dead quick'. OV2640 is a '2 Mega Pixel' camera. 2MP camera is usual for low end phones, high end phones have 5MP, some go to 8MP. Digital Cameras are usually 12 to 20 MP. Lets not discuss Nokia 41 MP. So 2 MP on the face of it is not very big.
I put '2 Mega Pixel' on purpose, maximum capture on OV2640 is UXGA = 1600x1200 pixels. Do the math 1600x1200=1,920,000 (not quite 2,000,000) though in raw mode there are extra pixels around border for interpolation. But that is pixels, not bytes, so we need to think of formats, typical RGB565, YUV422 are 16 bits (2 bytes) per pixel, so in those cases 3,840,000 bytes per frame. Now we need to think about frame speed (Frames Per Second - FPS). Normal video / viewfinder is 15 fps, though some do go to 30 fps.
So 15 fps UXGA = 3,840,000 * 15 = 57,600,000 bytes per second = 'A lot of data coming dead quick'.
Ok, I've reduced that by a ton, getting QVGA (320x240), I've now tried interrupts, I think the data is valid (but difficult to be sure), but I am not getting full frames, I really don't think Due can handle it.

How do phones do it, they are ARM based? I know Nokia, it isn't easy. Nokia had big problems, it was OK putting camera into first phone, it was high end, that means relatively low production, low sales. Putting it into low end phones = high volume, low cost, no single camera module manufacturer can handle producing the quantity of camera modules needed for a single low end phone. So Nokia and ST collaborated to produce the 'SMIA' (Standard Mobile Imaging Archecture) set of specifications. This means Nokia can buy SMIA compliant camera modules from a number of manufacturers and include in a phone.
Camera control is relatively low speed bi-directional handling 8 bit registers in phone, in almost all camera modules (including SMIA) this is based upon I2C (IIC, Inter Integrated-circuit Communications), I say 'based upon' as it is usually simplified, can't handle high speeds, changing speeds etc. There is usually no problem with controlling a camera.
For some unknown reason (maybe to do with language), the SMIA image data out port is called CCP (Camera Control Port, which it is NOT), the CCP port is special, it is very high speed sub-LVDS serial. It can be 2 wire (original) or these days single clock with multiple data lines, but in all cases it is fewer wires than parallel. It is sub-LVDS to make it ultra low noise to stop it interfering with phone RF (blocked channels). All Nokia chipsets have a special CCP input port block, the block includes the sub-LVDS pads and handles serial to parallel conversion as well as including a buffer, the ONLY way to get data out of this block is DMA. The size of the buffer was always a problem and always got increased in size for each chip revision.
If we were allowed to know (which we aren't), I believe you will find that the Broadcom processor built into the Raspberry Pi is actually an old obsolete design created for Nokia. It includes the CCP port block, it also includes the Broadcom Image pipeline. SMIA data comes from Camera Module over sub-LVDS to Nokia CCP block, it goes from CCP Block over DMA to Image pipeline, it then goes via DMA to RAM.
Almost all camera modules are either SMIA or can be SMIA, you are not allowed to use/view SMIA specifications unless you are a member of the MIPI alliance, you can't issue SMIA details (including data sheets that include SMIA details) unless you request an NDA. This is why it is so damned difficult to get information on camera modules. I was 'host software' support engineer during SMIA specification creation. Blame SMIA, MIPI, Nokia or me for the fact that you can't get camera module information!

There are things I can still try:
1) Simplify Pixel clock interrupt handler, make it more efficient, ditch range checking.
2) Switch to JPEG format for frames, compresses to 1 bit per pixel, if it is possible for lower size frames.
3) DMA from camera to RAM (some how).
4) External camera data receive / buffer (ArduCam uses a special chip).

1 & 2)
volatile int FrameCnt = 0; 

void CamCapture()
{
  FrameCnt++;
  //if (FrameCnt < MAX_FRAME)
  //  FrameBuf[FrameCnt++] = (byte)(REG_PIOC_PDSR & 0xff);
}

not completely repeatable, but maybe close enough, but it's not doing anything.
It I use long instead of int then it goes out the window.
For QCIF (176x144 lowest) in RGB565 I get 28170 bytes (28169 to 28173 over 10 attempts)
For QCIF in JPEG it's around 3560 bytes, but then JPEG will not be consistent.

Ok, Interrupt no good, try DMA
Spent most of today looking at DMA, the Due does not allow DMA source trigger from GPIO, only from in-built peripheral triggers.

That just leaves option 4, maybe a PIC?
This would actually be the best solution. I want something simple but fast. Clocks in parallel data synchronized with external trigger put into on board RAM. Fast SPI slave interface to allow RAM to be read. How hard can it be?
Why is it the best solution? It would work with Arduino Due or stand alone ESP8266.

2/2/2015
Examined camera pins with scope.
VSync is not pulsing high at start and end of frame, it goes high before start, goes low after end.
Major problem is Pixel Clk, it has really nasty 50 Hz hum hiding data. Should have checked this earlier, gone over HW App Notes and SW App Notes. HW notes say that if using a single supply for DOVDD and AVDD (as I am doing) then they should be seperated by RC filter which I have not done :-(
I'll revisit circuit (again) and see if I can cure it.
Then I can retry the interrupt capture.

14/2/2015
I fixed the problem, camera was being supplied with 12 MHz clock, settings were for 24 MHz clock. Altering settings to match clock fixed the weirdness.
Then I finally admitted defeat, Due DMA can not be used to capture frame bytes and Interrupt handling is too slow, if I slow it down enough that Due can handle it then image speed will be pointless. Even if I accept really low frame rates, there is not enough RAM in Due to hold a decent frame size.
Basically, Due attempt was pointless except as a learning exercise.

So, I need something more designed to handle camera. My current favorite is STM32F407VGT6TR, it is 14x14 LQFP with 100 pins, so I should be able to create a PCB for it. It has a purpose built Camera Interface that will connect to OV2640 and it has high speed SDCard Interface. I think I can program it to DMA frames from camera direct to SD Card. It costs a bit more than I wanted at just under £7. There is a dev platform with the chip called STM32F4DISCOVERY for £12, bought one.
It seems quite hard to set this up with any IDE that doesn't cost a fortune to license, but I'm looking into it.



No comments:

Post a Comment