Ethercard image transfer and Arducam

Hi there,

I'm trying to capture an image (jpg) with an Arducam Mini 5MP OV5640, my Arduino pro Mini 16 MHz and an ENC28J60 Ethernet-Adapter. The arduino should trigger the capturee when a special UDP-Message arrives. That works. After capture, I'd like to transfer the captured image to a server running a very simple python script to save incoming UDP-data.
However, capturing seems to work fine but there are several things I don't get really into:

  • If I output the FIFO-data it is only Int-values due to the fact that I read the FIFO-Data as uint8_t. I'd expect a jpeg is a sequence of bytes. But the SPI-library does not offer the possibility to read bytes from FIFO. Do I need to convert the Int-values into bytes?
  • When I print out the Int-values with Serial.println I get, as mentioned above, a sequence of Int-Values in the Serial-Monitor. On the Output of the python-server however I only get "crap", like also a "B" and things like that. What is going on there?

Actually it is not only about these questions, it's more how to get the program running as expected. Any help is highly appreciated. Thanks in advance!
Here is my code:

#include <Wire.h>
#include <ArduCAM.h>
#include <SPI.h>
#include "memorysaver.h"
#include <EtherCard.h>
#include <IPAddress.h>
//This demo can only work on OV5640_MINI_5MP_Plus platform.
#if !(defined OV5640_MINI_5MP_PLUS )
  #error Please select the hardware platform and camera module in the ../libraries/ArduCAM/memorysaver.h file
#endif
#define BMPIMAGEOFFSET 66
#define REQUEST_RATE 5000
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte hostip[] = { 192,168,178,21 };
const int dstPort PROGMEM = 1337;
const int srcPort PROGMEM = 4321;
// remote website name
const char website[] PROGMEM = "google.com";
uint8_t temp, temp_last;
bool is_header = false;
byte Ethernet::buffer[700];
static long timer;

static void my_result_cb (byte status, word off, word len) {
        Serial.print("<<< reply ");
        Serial.print(millis() - timer);
        Serial.println(" ms");
        Serial.println((const char*) Ethernet::buffer + off);
}

// set pin 7 as the slave select for the digital pot:
const int CS = 7;

ArduCAM myCAM( OV5640, CS );
//uint8_t read_fifo_burst(ArduCAM myCAM);

void serverCapture(){
        byte buf[256];
        static int i = 0;
        uint8_t temp = 0,temp_last=0;
        uint32_t length = 0;
        bool is_header = false;
//Flush the FIFO
        myCAM.flush_fifo();
//Clear the capture done flag
        myCAM.clear_fifo_flag();
//Start capture
        myCAM.start_capture();
        Serial.println(F("start Capture"));
        while(!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)) ;
        Serial.println(F("Capture Done."));
        length = myCAM.read_fifo_length();
        Serial.print(F("The fifo length is :"));
        Serial.println(length, DEC);
        if (length >= MAX_FIFO_SIZE) //384K
        {
                Serial.println(F("Over size."));
                return;
        }
        if (length == 0 ) //0 kb
        {
                Serial.println(F("Size is 0."));
                return;
        }

        myCAM.CS_LOW();
        myCAM.set_fifo_burst();
        while ( length-- )
        {
                temp_last = temp;
                temp =  SPI.transfer(0x00);
                Serial.println(temp);
                //Read JPEG data from FIFO
                if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
                {
                        buf[i++] = temp; //save the last  0XD9
                        //Write the remain bytes in the buffer
                        myCAM.CS_HIGH();
                        ether.sendUdp(buf, i, srcPort, hostip, dstPort);
                        Serial.println(F("Image save OK."));
                        is_header = false;
                        i = 0;
                }
                if (is_header == true)
                {
                        //Write image data to buffer if not full
                        if (i < 256)
                                buf[i++] = temp;
                        else
                        {
                                //Write 256 bytes image data to file
                                myCAM.CS_HIGH();
                                ether.sendUdp(buf, 256, srcPort, hostip, dstPort);
                                i = 0;
                                buf[i++] = temp;
                                myCAM.CS_LOW();
                                myCAM.set_fifo_burst();
                        }
                }
                else if ((temp == 0xD8) & (temp_last == 0xFF))
                {
                        is_header = true;
                        buf[i++] = temp_last;
                        buf[i++] = temp;
                }
        }
}

void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[IP_LEN], uint16_t src_port, const char *data, uint16_t len){
        IPAddress src(src_ip[0],src_ip[1],src_ip[2],src_ip[3]);

        Serial.print("dest_port: ");
        Serial.println(dest_port);
        Serial.print("src_port: ");
        Serial.println(src_port);

        Serial.print("src_port: ");
        ether.printIp(src_ip);
        Serial.println("data: ");
        Serial.println(data);
        serverCapture();
}

void setup() {
        uint8_t vid, pid;
        uint8_t temp;
#if defined(__SAM3X8E__)
        Wire1.begin();
        Serial.begin(115200);
#else
        Wire.begin();
        Serial.begin(115200);
#endif
        Serial.println(F("ACK CMD ArduCAM Start!"));
// set the CS as an output:
        pinMode(CS, OUTPUT);
// initialize SPI:
        SPI.begin();
        while(1) {
                //Check if the ArduCAM SPI bus is OK
                myCAM.write_reg(ARDUCHIP_TEST1, 0x55);
                temp = myCAM.read_reg(ARDUCHIP_TEST1);
                if (temp != 0x55) {
                        Serial.println(F("ACK CMD SPI interface Error!"));
                        delay(1000); continue;
                }else{
                        Serial.println(F("ACK CMD SPI interface OK.")); break;
                }
        }
        while(1) {
                //Check if the camera module type is OV5642
                myCAM.wrSensorReg16_8(0xff, 0x01);
                myCAM.rdSensorReg16_8(OV5640_CHIPID_HIGH, &vid);
                myCAM.rdSensorReg16_8(OV5640_CHIPID_LOW, &pid);
                if((vid != 0x56) || (pid != 0x40)) {
                        Serial.println(F("ACK CMD Can't find OV5640 module!"));
                        delay(1000); continue;
                }
                else{
                        Serial.println(F("ACK CMD OV5640 detected.")); break;
                }
        }
//Change to JPEG capture mode and initialize the OV5642 module
        myCAM.set_format(JPEG);
        myCAM.InitCAM();
        myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK); //VSYNC is active HIGH
        myCAM.OV5640_set_JPEG_size(OV5640_320x240);
        delay(1000);
        myCAM.clear_fifo_flag();
        myCAM.write_reg(ARDUCHIP_FRAMES,0x00);

        Serial.println("\n[getDHCPandDNS]");

        if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
                Serial.println( "Failed to access Ethernet controller");

        if (!ether.dhcpSetup())
                Serial.println("DHCP failed");

        ether.printIp("My IP: ", ether.myip);
// ether.printIp("Netmask: ", ether.mymask);
        ether.printIp("GW IP: ", ether.gwip);
        ether.printIp("DNS IP: ", ether.dnsip);

        if (!ether.dnsLookup(website))
                Serial.println("DNS failed");
        ether.printIp("Server: ", ether.hisip);

        timer = -REQUEST_RATE; // start timing out right away

        ether.udpServerListenOnPort(&udpSerialPrint, 1337);

//register udpSerialPrint() to port 42.
        ether.udpServerListenOnPort(&udpSerialPrint, 42);
}





void loop() {
        uint8_t temp = 0xff, temp_last = 0;
        ether.packetLoop(ether.packetReceive());
}

And the python server-script:

# ----- receiver.py -----

#!/usr/bin/env python

from socket import *
import sys
import select

host="192.168.178.21"
port = 1337
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))

addr = (host,port)
buf=1024

data,addr = s.recvfrom(buf)
print "Received File:"
f = open("out.jpg",'wb')

data, addr = s.recvfrom(buf)
try:
    while(data):
        f.write(data)
        s.settimeout(5)
        data,addr = s.recvfrom(buf)
except timeout:
    f.close()
    s.close()
    print "File Downloaded"

This is the output of an "image":

0 255 216 255 224 0 16 74 70 73 70 0 1 1 1 0 0 0 0 0 0 255 219 0 67 0 4 3 3 4 3 3 4 4 3 4 5 4 4 5 6 10 7 6 6 6 6 12 9 9 7 10 15 13 15 15 14 13 14 14 16 18 23 20 16 17 22 17 14 14 20 27 20 22 24 25 26 26 26 16 19 28 30 28 2 5 30 23 25 26 25 255 219 0 67 1 4 5 5 6 5 6 12 7 7 12 25 17 14 17 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 255 19 6 0 31 0 0 1 5 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 255 196 0 181 16 0 2 1 3 3 2 4 3 5 5 4 4 0 0 1 125 1 2 3 0 4 17 5 18 33 49 65 6 19 81 97 7 34 113 20 50 129 145 161 8 35 66 177 193 21 82 209 240 36 51 98 114 130 9 10 22 23 24 25 26 37 38 39 40 41 42 52 53 54 55 56 57 58 67 68 69 70 71 72 73 74 83 84 85 86 87 88 89 90 99 100 101 102 103 104 105 106 115 116 117 118 119 120 121 122 131 132 133 134 135 136 137 138 146 147 148 149 150 151 152 153 154 162 163 164 165 166 167 168 169 170 178 179 180 181 182 183 184 185 186 194 195 196 197 198 199 200 201 202 210 211 212 213 214 215 216 217 218 225 226 227 228 229 230 231 232 233 234 241 242 243 24 4 245 246 247 248 249 250 255 196 0 31 1 0 3 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 255 196 0 18 1 17 0 2 1 2 4 4 3 4 7 5 4 4 0 1 2 119 0 1 2 3 17 4 5 33 49 6 18 65 81 7 97 113 19 34 50 129 8 20 66 145 161 17

If I output the FIFO-data it is only Int-values due to the fact that I read the FIFO-Data as uint8_t. I'd expect a jpeg is a sequence of bytes.

The output is NOT int values. It IS byte values.

const char website[] PROGMEM = "google.com";

How is THAT relevant?

What, exactly, does ether.sendUdp() do? A link to the relevant library is definitely in order.

buf=1024

What, exactly, is this doing? It looks to me like it is assigning the value 1024 to some untyped variable called buf. How that makes buf an array is a mystery.

If it does, why does the buffer size on the PC not match the buffer size on the Arduino?