First release
Dependencies: EthernetInterface HTTPServer TextLCD mbed-rpc mbed-rtos mbed
Sample code of section 5 in Oct 2014 issue of the Interface Magazine, published by CQ publishing in Japan. CQ出版社インターフェース誌 2014年10月号5章に掲載のサンプルコードです.
LPC1768にトラ技OV7670モジュールとサーボを接続したうえで,リモート操作可能なネットワーク・カメラにしています.このコードのうちカメラ制御部には,Sadaei Osakabe氏のコードを流用させていただいています.
また,次のHTMLファイルをダウンロードして,LPC1768のフラッシュメモリに置いてください.ネットワーク経由で,このHTMLにアクセスをします(ブラウザで開く). /media/uploads/smorioka/netcam.htm
main.cpp
- Committer:
- smorioka
- Date:
- 2014-08-26
- Revision:
- 0:993f719c9352
File content as of revision 0:993f719c9352:
/* * Copyright (c) 2014, Sumio Morioka * All rights reserved. * * This source code was originally written by Dr.Sumio Morioka for use in the Oct 2014 issue of * "the Interface magazine", published by CQ publishing Co.Ltd in Japan (http://www.cqpub.co.jp). * The author has no responsibility on any results caused by using this code. * * - Distribution date of this code: Aug 26, 2014 * - Author: Dr.Sumio Morioka (http://www002.upp.so-net.ne.jp/morioka) * * * IMPORTANT NOTICE: * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mbed.h" #include "mbed_rpc.h" #include "TextLCD.h" #include "LocalFileSystem.h" #include "EthernetInterface.h" #include "HTTPServer.h" #include "FsHandler.h" #include "RpcHandler.h" #include "ov7670.h" TextLCD lcd(p24, p26, p27, p28, p29, p30); //#define USE_RPCOUT #undef USE_RPCOUT #ifndef USE_RPCOUT DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); PwmOut sv0(p21), sv1(p22), sv2(p23); #else RpcDigitalOut led1(LED1, "led1"); RpcDigitalOut led2(LED2, "led2"); RpcDigitalOut led3(LED3, "led3"); RpcDigitalOut led4(LED4, "led4"); RpcPwmOut sv0(p21, "sv0"); RpcPwmOut sv1(p22, "sv1"); RpcPwmOut sv2(p23, "sv2"); #endif LocalFileSystem local("webfs"); OV7670 camera( p9,p10, // SDA,SCL(I2C / SCCB) p5,p6,p7, // VSYNC,HREF,WEN(FIFO) p20,p19,p18,p17,p16,p15,p14,p13, // D7-D0 p8,p11,p12); // RRST,OE,RCLK //Timer tmr; #define QQVGA //#define QVGA //#define VGA34 #ifdef QQVGA #define SIZEX 160 #define SIZEY 120 #endif #ifdef QVGA #define SIZEX 320 #define SIZEY 240 #endif #ifdef VGA34 #define SIZEX 480 #define SIZEY 360 #endif //void cam_cap(void); void cam_cap(Arguments* input, Reply* output); RPCFunction rpcFunc(&cam_cap, "cam_cap"); #ifndef USE_RPCOUT float sv0_rpc; float sv1_rpc; float sv2_rpc; RPCVariable<float> rpc_sv0_val(&sv0_rpc, "sv0"); RPCVariable<float> rpc_sv1_val(&sv1_rpc, "sv1"); RPCVariable<float> rpc_sv2_val(&sv2_rpc, "sv2"); #endif int cap_flag; RPCVariable<int> rpc_cap_flag(&cap_flag, "cap_flag"); int memfree(void) { int ret = 1; while (1) { char *p = (char *)malloc(ret); if (p == NULL) break; free(p); ret++; } return (ret); } float deg_to_pulsewidth(float deg) { // limit range if (deg < -90.0f) deg = -90.0f; else if (deg > 90.0f) deg = 90.0f; // return result return (0.00145f + 0.001f * (deg / 90.0f)); } int main() { float sv0_val, sv1_val, sv2_val; #ifndef USE_RPCOUT led1 = 0; led2 = 0; led3 = 0; led4 = 0; #else led1.write(0); led2.write(0); led3.write(0); led4.write(0); #endif #ifdef USE_RPCOUT sv0_val = 0.00045f; // unit: sec sv1_val = 0.00145f; // unit: sec sv2_val = 0.00245f; // unit: sec sv0.period(0.02f); // unit: sec sv0.pulsewidth(sv0_val); sv1.period(0.02f); // unit: sec sv1.pulsewidth(sv1_val); sv2.period(0.02f); // unit: sec sv2.pulsewidth(sv2_val); #else sv0_val = 0.0f; // unit: deg sv1_val = 0.0f; // unit: deg sv2_val = 0.0f; // unit: deg sv0.period(0.02f); // unit: sec sv0.pulsewidth(deg_to_pulsewidth(sv0_val)); sv1.period(0.02f); // unit: sec sv1.pulsewidth(deg_to_pulsewidth(sv1_val)); sv2.period(0.02f); // unit: sec sv2.pulsewidth(deg_to_pulsewidth(sv2_val)); sv0_rpc = sv0_val; sv1_rpc = sv1_val; sv2_rpc = sv2_val; #endif cap_flag = 0; //////////////////////////////////////////////////////////////////////////// camera.WriteReg(0x12, 0x80); // com7; reset wait_ms(200); camera.InitDefaultReg(); // negate vsync camera.WriteReg(0x15, 0x02); // com10; negative vsync #ifdef QQVGA camera.InitQQVGA(); #endif #ifdef QVGA camera.InitQVGA(); #endif #ifdef VGA34 camera.InitVGA_3_4(); #endif // data format camera.WriteReg(0x12, 0x04 + 0); // com7 RGB (bit1...test pattern) camera.WriteReg(0x40, 0xD0); // com15 RGB565 camera.WriteReg(0x8c, 0x00); // RGB444 wait_ms(300); //{ //FILE *f = fopen("/webfs/REG.TXT", "wt"); //for (int i = 0; i < 256; i++) { // int val = camera.ReadReg(i); // fprintf(f, "%02X ", val); // if ((i % 16) == 15) // fprintf(f, "\n"); //} //fclose(f); //} ////////////////////////////////////////////////// // network EthernetInterface eth; // locate here // //Static IP // char *ip = "192.168.0.20"; // char *mask = "255.255.255.0"; // char *gateway = "192.168.0.1"; // eth.init(ip, mask, gateway); //DHCP eth.init(); eth.connect(); lcd.locate(0, 0); lcd.printf("IP %s", eth.getIPAddress()); // rcp #ifdef USE_RPCOUT // RPC::add_rpc_class<RpcDigitalIn>(); // read RPC::add_rpc_class<RpcDigitalOut>(); // read,write // RPC::add_rpc_class<RpcDigitalInOut>(); // read,write,input,output RPC::add_rpc_class<RpcPwmOut>(); // read,write,period,period_ms,pulsewidth,pulsewidth_ms // RPC::add_rpc_class<RpcAnalogIn>(); // read,read_u16 // RPC::add_rpc_class<RpcAnalogOut>(); // read,write,write_u16 // RPC::add_rpc_class<RpcSPI>(); // format,frequency,write // RPC::add_rpc_class<RpcSerial>(); // baud,readable,writeable(SPELL?),putc,getc,puts // RPC::add_rpc_class<RpcTimer>(); // start,stop,reset,read,read_ms,read_us #endif // http HTTPServer svr; // locate here HTTPFsRequestHandler::mount("/webfs/", "/"); svr.addHandler<HTTPFsRequestHandler>("/"); svr.addHandler<HTTPRpcRequestHandler>("/rpc"); svr.start(80, ð); // lcd.locate(0, 1); // lcd.printf("mem %d", memfree()); #ifndef USE_RPCOUT led1 = 1; #else led1.write(1); #endif while (1) { svr.poll(); #ifndef USE_RPCOUT if (sv0_val != sv0_rpc) { sv0_val = sv0_rpc; // limit if (sv0_val < -90.0f) sv0_val = -90.0f; else if (sv0_val > 90.0f) sv0_val = 90.0f; sv0_rpc = sv0_val; sv0.pulsewidth(deg_to_pulsewidth(sv0_val)); lcd.locate(0, 1); lcd.printf("0:%f ", sv0_val); } if (sv1_val != sv1_rpc) { sv1_val = sv1_rpc; // limit if (sv1_val < -90.0f) sv1_val = -90.0f; else if (sv1_val > 90.0f) sv1_val = 90.0f; sv1_rpc = sv1_val; sv1.pulsewidth(deg_to_pulsewidth(sv1_val)); lcd.locate(0, 1); lcd.printf("1:%f ", sv1_val); } if (sv2_val != sv2_rpc) { sv2_val = sv2_rpc; // limit if (sv2_val < -90.0f) sv2_val = -90.0f; else if (sv2_val > 90.0f) sv2_val = 90.0f; sv2_rpc = sv2_val; sv2.pulsewidth(deg_to_pulsewidth(sv2_val)); lcd.locate(0, 1); lcd.printf("2:%f ", sv2_val); } #endif wait_ms(10); } } //void cam_capture(char *input, char *output) // compile error void cam_cap(Arguments* input, Reply* output) //void cam_cap(void) { FILE *fp_bmp; unsigned int d1, d2; unsigned char sort[3]; #ifndef USE_RPCOUT led2 = 1; #else led2.write(1); #endif cap_flag = 0; fp_bmp = fopen("/webfs/cam.bmp", "wb"); ///////////////////////// // file header ///////////////////////// fprintf(fp_bmp, "BM"); int val = 14 + 40 + SIZEX * SIZEY * 3; // file size fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000); fprintf(fp_bmp, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0x36, 0, 0, 0); ///////////////////////// // information header ///////////////////////// fprintf(fp_bmp, "%c%c%c%c", 0x28, 0, 0, 0); // header size fprintf(fp_bmp, "%c%c%c%c", SIZEX % 0x100, SIZEX / 0x100, SIZEX / 0x10000, SIZEX / 0x1000000); fprintf(fp_bmp, "%c%c%c%c", SIZEY % 0x100, SIZEY / 0x100, SIZEY / 0x10000, SIZEY / 0x1000000); fprintf(fp_bmp, "%c%c", 1, 0); // # of plane fprintf(fp_bmp, "%c%c", 24, 0); // bit count fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0); // compression val = SIZEX * SIZEY * 3; // data size fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000); fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0); fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0); fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0); fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0); camera.CaptureNext(); // sample start! while(camera.CaptureDone() == false) ; camera.ReadStart(); // reset pointer #ifndef USE_RPCOUT led3 = 1; #else led3.write(1); #endif for (int y = 0;y < SIZEY;y++) { for (int x = 0;x < SIZEX;x++) { d1 = camera.ReadOneByte() ; // upper nibble is XXX , lower nibble is B d2 = camera.ReadOneByte() ; // upper nibble is G , lower nibble is R // RGB565 sort[0] = ((d1 & 0xF8) >> 3) << 3; // R sort[1] = ( ((d1 & 0x07) << 3) + ((d2 & 0xE0) >> 5) ) << 2; // G sort[2] = (d2 & 0x1F) << 3; // B fprintf(fp_bmp, "%c%c%c", sort[2], sort[1], sort[0]); // B,G,R } } camera.ReadStop(); fclose(fp_bmp); #ifndef USE_RPCOUT led2 = 0; led3 = 0; led4 = 0; #else led2.write(0); led3.write(0); led4.write(0); #endif cap_flag = 1; } // end of file