Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: T3.6 + Arducam Mini2MP = recording 320x240 14 FPS on microSD :)

  1. #1
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    100

    T3.6 + Arducam Mini2MP = recording 320x240 14 FPS on microSD :)

    With the latest Arducam library, I've finally managed to have a working sketch with Teensy 3.6 recording video from the Arducam Mini2MP module and saving it to the onboard microSD.
    Output format is MJPEG AVI.
    Due probably to some bottleneck inside the Arducam module (OV2640->AL422->MAXX 2->SPI) I can't pull more than 14 FPS at 320x240: not top-notch video, but not bad after all.
    Unfortunately, it drops to 3.7 FPS if switching to VGA capture (640x480).
    The Arducam Mini2MP module is nice: cheap, easy to connect (SCCB which really is I2C for control, SPI for data).

    Here's the sketch, adapted from a (then non-working) example from Arducam library (remember to pull the latest Arducam library and to configure its memorysaver.h):

    Code:
    // ArduCAM Mini demo (C)2017 Lee
    // Web: http://www.ArduCAM.com
    // This program is a demo of how to use most of the functions
    // of the library with ArduCAM Mini camera, and can run on any Arduino platform.
    // This demo was made for ArduCAM Mini Camera.
    //This demo timed 5 seconds to record video.
    // It can shoot video and store it into the SD card
    // The demo sketch will do the following tasks
    // 1. Set the camera to JPEG output mode.
    // 2. Capture a JPEG photo and buffer the image to FIFO
    // 3.Write AVI Header
    // 4.Write the video data to the SD card
    // 5.More updates AVI file header
    // 6.close the file
    //The file header introduction
    //00-03 :RIFF
    //04-07 :The size of the data
    //08-0B :File identifier
    //0C-0F :The first list of identification number
    //10-13 :The size of the first list
    //14-17 :The hdr1 of identification
    //18-1B :Hdr1 contains avih piece of identification 
    //1C-1F :The size of the avih
    //20-23 :Maintain time per frame picture
    
    // This program requires the ArduCAM V4.0.0 (or later) library and ArduCAM Mini camera
    // and use Arduino IDE 1.6.8 compiler or above
    
    // FC aka XFer: last edit 20181106
    // 14 FPS sustained on Teensy 3.6 at 320x240, with subject movement (87 KB/s max data rate)
    // Drops to 3.8 FPS at 640x480: we simply don't get more speed from the camera. FIFO bandwidth issue? CPLD bandwidth issue?
    // Note: Mini2MP module has onboard 7K pullups on I2C. We can do without external pullups if wires are kept short
    
    // TODO: 
    // Preallocate output file (create at max length, fill with 0, rewind, then truncate to actual bytes written after capture finished)
    
    #include <stdint.h>
    #include <Wire.h>
    #include <ArduCAM.h>
    #include <SPI.h>
    #include <SdFat.h>  // Use the excellent SdFat library https://github.com/greiman/SdFat
    #include "memorysaver.h"
    
    // THIS VERSION IS FOR TEENSY 3.5/3.6 https://www.pjrc.com/store/
    
    // DEFINES
    //This demo can only work on OV2640_MINI_2MP or OV5642_MINI_5MP or OV5642_MINI_5MP_BIT_ROTATION_FIXED platform.
    #if !(defined OV5642_MINI_5MP || defined OV5642_MINI_5MP_BIT_ROTATION_FIXED || defined OV2640_MINI_2MP|| defined OV3640_MINI_3MP)
      #error Please select the hardware platform and camera module in the ../libraries/ArduCAM/memorysaver.h file
    #endif
    #define SERIAL_SPEED 115200
    #define BUFFSIZE 4096   // Good compromise between latency and write speed on T3.5/3.6
    #define FRAME_SIZE OV2640_320x240 // OV2640_640x480 
    #define WIDTH_1 0x40    // 320 (Big Endian: 320 = 0x01 0x40 -> 0x40 0x01). For 640: 0x80 0x02
    #define WIDTH_2 0x01 
    #define HEIGHT_1 0xF0   // 240 (0x00 0xF0 -> 0xF0 0x00). For 480: 0xE0 0x01	
    #define HEIGHT_2 0x00 
    #define FPS 0x0F // 15 FPS. Placeholder: will be overwritten at runtime based upon real FPS attained
    #define TOTAL_FRAMES 200	// Number of frames to be recorded. If < 256, easier to recognize in header (for manual hex debug)
    //set pin 7 as the slave select for SPI:
    #define SPI_CS  7
    #define AVIOFFSET 240 // AVI main header length
    
    // GLOBALS
    SdFatSdioEX SD; // Much more efficient than standard SD, expecially on Teensy 3.5-3.6 (up to 18 MB/s write speed!)
    unsigned long movi_size = 0;
    unsigned long jpeg_size = 0;
    const char zero_buf[4] = {0x00, 0x00, 0x00, 0x00};
    const int avi_header[AVIOFFSET] PROGMEM ={
      0x52, 0x49, 0x46, 0x46, 0xD8, 0x01, 0x0E, 0x00, 0x41, 0x56, 0x49, 0x20, 0x4C, 0x49, 0x53, 0x54,
      0xD0, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x6C, 0x61, 0x76, 0x69, 0x68, 0x38, 0x00, 0x00, 0x00,
      0xA0, 0x86, 0x01, 0x00, 0x80, 0x66, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
      0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      WIDTH_1, WIDTH_2, 0x00, 0x00, HEIGHT_1, HEIGHT_2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54, 0x84, 0x00, 0x00, 0x00,
      0x73, 0x74, 0x72, 0x6C, 0x73, 0x74, 0x72, 0x68, 0x30, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x73,
      0x4D, 0x4A, 0x50, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x01, 0x00, 0x00, 0x00, FPS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x66,
      0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, WIDTH_1, WIDTH_2, 0x00, 0x00, HEIGHT_1, HEIGHT_2, 0x00, 0x00,
      0x01, 0x00, 0x18, 0x00, 0x4D, 0x4A, 0x50, 0x47, 0x00, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54,
      0x10, 0x00, 0x00, 0x00, 0x6F, 0x64, 0x6D, 0x6C, 0x64, 0x6D, 0x6C, 0x68, 0x04, 0x00, 0x00, 0x00,
      0x64, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54, 0x00, 0x01, 0x0E, 0x00, 0x6D, 0x6F, 0x76, 0x69,
    };
    #if defined (OV2640_MINI_2MP)
      ArduCAM myCAM( OV2640, SPI_CS );
    #elif defined (OV3640_MINI_3MP)
      ArduCAM myCAM( OV3640, SPI_CS );
    #else
      ArduCAM myCAM( OV5642, SPI_CS );
    #endif
    // END GLOBALS
    
    
    static void inline print_quartet(unsigned long i,File fd)
    { // Writes an uint32_t in Big Endian at current file position
      fd.write(i % 0x100);  i = i >> 8;   //i /= 0x100;
      fd.write(i % 0x100);  i = i >> 8;   //i /= 0x100;
      fd.write(i % 0x100);  i = i >> 8;   //i /= 0x100;
      fd.write(i % 0x100);
    }
    
    static void Video2SD()
    {	// We don't enforce FPS: we just record and save frames as fast as possible
    	// Then we compute the attained FPS and update the AVI header accordingly
    	char str[8];
        uint16_t n;
    	File outFile;
    	byte buf[BUFFSIZE];
    	static int i = 0;
    	uint8_t temp = 0, temp_last = 0;
    	unsigned long fileposition = 0;
    	uint16_t frame_cnt = 0;
    	uint16_t remnant = 0;
    	uint32_t length = 0;
    	uint32_t startms;
    	uint32_t elapsedms;
        uint32_t uVideoLen = 0;
    	bool is_header = false;
    
    
    	// Create a avi file. Try it to be unique, but short	
        randomSeed(analogRead(0) * millis());
        n = (random(2,999));    // Don't use 1.avi: was the default in old code, we don't want to overwrite old recordings
        itoa(n, str, 10);
            strcat(str, ".avi");
        Serial.print("\nFile name will be "); Serial.println(str);
      
    	//Open the new file
    	outFile = SD.open(str, O_WRITE | O_CREAT | O_TRUNC);
    	if (! outFile)
    	{
    	  Serial.println(F("File open failed"));
    	  while (1);
    	  return;
    	}
    
    
    	//Write AVI Main Header
    	// Some entries will be overwritten later
    	for ( i = 0; i < AVIOFFSET; i++)
    	{
    	  char ch = pgm_read_byte(&avi_header[i]);
    	  buf[i] = ch;
    	}
    	outFile.write(buf, AVIOFFSET);
      
        Serial.print(F("\nRecording "));
        Serial.print(TOTAL_FRAMES); 
        Serial.println(F(" video frames: please wait...\n"));
    
    	startms = millis();
    
      //Write video data, frame by frame
    	for ( frame_cnt = 0; frame_cnt < TOTAL_FRAMES; frame_cnt++)
    	{
    	  #if defined (ESP8266)
    	  yield();
    	  #endif
    	  temp_last = 0;temp = 0;
    	  //Capture a frame            
    	  //Flush the FIFO
    	  myCAM.flush_fifo();
    	  //Clear the capture done flag
    	  myCAM.clear_fifo_flag();
    	  //Start capture
    	  myCAM.start_capture();
        // Wait for frame ready
    	  while (!myCAM.get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK));
    	  length = myCAM.read_fifo_length();	// Length of FIFO buffer. In general, it contains more than 1 JPEG frame;
                                                // so we'll have to check JPEG markers to save a single JPEG frame
    #if defined(SPI_HAS_TRANSACTION)
          SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
        #endif
    
    	  // Deassert camera Chip Select to start SPI transfer
    	  myCAM.CS_LOW();
    
    	// Write segment. We store 1 frame for each segment (video chunk)
    	  outFile.write("00dc");	// "start of video data chunk" (00 = data stream #0, d = video, c = "compressed")
    	  outFile.write(zero_buf, 4);	// Placeholder for actual JPEG frame size, to be overwritten later
    	  i = 0;
    	  jpeg_size = 0;
        // Set FIFO to burst read mode
    	  myCAM.set_fifo_burst();
        // Transfer data, a byte at a time
    	  while ( length-- )
    	  {	// For every byte in the FIFO...
      		#if defined (ESP8266)
      		yield();
      		#endif
    		// We always need the last 2 bytes, to check for JPEG begin/end markers
      		temp_last = temp; // Save current temp value
      		temp =  SPI.transfer(0x00); // Overwrite temp with 1 byte from FIFO (0x00 is dummy byte for the slave: we are reading, the slave will ignore it)
          #if defined(SPI_HAS_TRANSACTION)
            SPI.endTransaction();
          #endif     
    		// a JPEG ends with the two bytes 0xFF, 0xD9
      		if ( (temp == 0xD9) && (temp_last == 0xFF) ) //	End of the image
      		{
      		  buf[i++] = temp;  // Add this last byte to the buffer
      		  myCAM.CS_HIGH();  // End of transfer: re-assert Slave Select
    		  // Write the buffer to file
    		  outFile.write(buf, i);
      		  is_header = false;	// We are at the last byte of the JPEG: sure is not the header :) 
      		  jpeg_size += i;		// Update total jpeg size with this last buffer size
      		  i = 0;				// Reset byte counter (restart writing from the first element of the buffer)
      		}  
      		if (is_header == true)  // Not at end of JPEG, yet
      		{ 
      		  //Write image data to buffer if not full
      		  if (i < BUFFSIZE)
      			  buf[i++] = temp;
      		  else
      		  { // Buffer is full: transfer to file
        			//Write BUFFSIZE bytes image data to file
        			myCAM.CS_HIGH();  // End SPI transfer
        			outFile.write(buf, BUFFSIZE);
        			i = 0;	// Restart writing from the first element
        			buf[i++] = temp;	// Save current byte as first in "new" buffer
        			myCAM.CS_LOW();   // Re-enable SPI transfer
        			myCAM.set_fifo_burst();	// Set FIFO to burst read mode 
        			jpeg_size += BUFFSIZE;
      		  }        
      		}
      		else if ((temp == 0xD8) & (temp_last == 0xFF))
      		{	// A JPEG starts with the two bytes 0xFF, 0XD8; so here we are at the beginning of the JPEG
      		  is_header = true;	
      		  buf[i++] = temp_last;	// Save the first two bytes (off-cycle)
      		  buf[i++] = temp;   
      		} 
    	  }	// end loop over each byte in the FIFO: JPEG is complete    
        
          // Padding	  
    	  remnant = jpeg_size & 0x00000001;	// Align to 16 bit: add 0 or 1 "0x00" bytes
          if (remnant > 0)
          {
    	  //  jpeg_size += remnant; // Wrong: jpeg_size and movi_size should not include padding:
            outFile.write(zero_buf, remnant); // see https://docs.microsoft.com/en-us/windows/desktop/directshow/avi-riff-file-reference
          }
    
    	  movi_size += jpeg_size;	// Update totals
    	  uVideoLen += jpeg_size;   // <- This is for statistics only
    
    	  // Now we have the real frame size in bytes. Time to overwrite the placeholder
    
    	  fileposition = outFile.position();  // Here, we are at end of chunk (after padding)
    	  outFile.seek(fileposition - jpeg_size - remnant - 4); // Here we are the the 4-bytes blank placeholder      
    	  print_quartet(jpeg_size, outFile);    // Overwrite placeholder with actual frame size (without padding)
          outFile.seek(fileposition - jpeg_size - remnant + 6); // Here is the FOURCC "JFIF" (JPEG header)
          outFile.write("AVI1", 4);         // Overwrite "JFIF" (still images) with more appropriate "AVI1"     
    
    	  // Return to end of JPEG, ready for next chunk
    	  outFile.seek(fileposition);
    	}	// End cycle for all frames
      // END CAPTURE
      
        // Compute statistics
    	elapsedms = millis() - startms;
    	float fRealFPS = (1000.0f * (float)frame_cnt) / ((float)elapsedms);
    	float fmicroseconds_per_frame = 1000000.0f / fRealFPS;
    	uint8_t iAttainedFPS = round(fRealFPS); // Will overwrite AVI header placeholder
    	uint32_t us_per_frame = round(fmicroseconds_per_frame); // Will overwrite AVI header placeholder
    
    	//Modify the MJPEG header from the beginning of the file, overwriting various placeholders
    	outFile.seek(4);
    	print_quartet(movi_size + 12*frame_cnt + 4, outFile); //    riff file size
    	//overwrite hdrl
    	//hdrl.avih.us_per_frame:
    	outFile.seek(0x20);
    	print_quartet(us_per_frame, outFile);
    	unsigned long max_bytes_per_sec = movi_size * iAttainedFPS / frame_cnt; //hdrl.avih.max_bytes_per_sec
    	outFile.seek(0x24);
    	print_quartet(max_bytes_per_sec, outFile);
    	//hdrl.avih.tot_frames
    	outFile.seek(0x30);
    	print_quartet(frame_cnt, outFile);
        outFile.seek(0x84);
        print_quartet((int)iAttainedFPS, outFile);
    	//hdrl.strl.list_odml.frames
    	outFile.seek(0xe0);
    	print_quartet(frame_cnt, outFile);
    	outFile.seek(0xe8);
    	print_quartet(movi_size, outFile);// size again
    	myCAM.CS_HIGH();
    	//Close the file
    	outFile.close();
    
    	Serial.println(F("\n*** Video recorded and saved ***\n"));
        Serial.print(F("Recorded "));
    	Serial.print(elapsedms / 1000);
    	Serial.print(F("s in "));
    	Serial.print(frame_cnt);
    	Serial.print(F(" frames\nFile size is "));
    	Serial.print(movi_size + 12*frame_cnt + 4);
    	Serial.print(F(" bytes\nActual FPS is "));
    	Serial.print(fRealFPS, 2);
    	Serial.print(F("\nMax data rate is "));
    	Serial.print(max_bytes_per_sec);
    	Serial.print(F(" byte/s\nFrame duration is "));
    	Serial.print(us_per_frame);
    	Serial.println(F(" us"));
        Serial.print(F("Average frame length is "));
        Serial.print(uVideoLen / TOTAL_FRAMES);
        Serial.println(F(" bytes"));
    }
    
    ////////////
    //
    //  SETUP
    //
    ////////////
    
    void setup()
    {
    	uint8_t vid, pid;
    	uint8_t temp;
    
    	Wire.begin();
    	Serial.begin(SERIAL_SPEED);
    	while(!Serial);
    
    	Serial.println(F("ArduCAM Start!\n"));
    	// set the SPI_CS as an output:
    	pinMode(SPI_CS, OUTPUT);
    	digitalWrite(SPI_CS, HIGH);
    	delay(1000);
    	// initialize SPI:
    	SPI.begin();
      
    	//Reset the CPLD
    	myCAM.write_reg(0x07, 0x80);
    	delay(100);
    	myCAM.write_reg(0x07, 0x00);
    	delay(100);
      
    	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("SPI interface Error!"));
    		delay(1000);continue;
    	  }else{
    		Serial.println(F("SPI interface OK."));break;
    	  }
    	}
    	//Initialize SD Card
    	while(!SD.begin()){
    	  Serial.println(F("SD Card Error!"));delay(1000);
    	}
    	Serial.println(F("SD Card detected."));
    	SD.chvol();
    
    	#if defined (OV2640_MINI_2MP)
    	while(1)
    	{
    	  //Check if the camera module type is OV2640
    	  myCAM.wrSensorReg8_8(0xff, 0x01);
    	  myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
    	  myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
    	  if ((vid != 0x26 ) && (( pid != 0x41 ) || ( pid != 0x42 )))
    	  {
    		Serial.println(F("Can't find OV2640 module!"));
    		delay(1000);continue;
    	  }
    	  else{
    	   Serial.println(F("OV2640 detected."));break;
    	  } 
    	}
    	#elif defined (OV3640_MINI_3MP)
    	  while(1){
    		//Check if the camera module type is OV3640
    		myCAM.rdSensorReg16_8(OV3640_CHIPID_HIGH, &vid);
    		myCAM.rdSensorReg16_8(OV3640_CHIPID_LOW, &pid);
    		if ((vid != 0x36) || (pid != 0x4C)){
    		  Serial.println(F("Can't find OV3640 module!"));
    		  delay(1000);continue; 
    		}else{
    		  Serial.println(F("OV3640 detected."));break;    
    		}
    	 } 
    	#else
    	while(1){
    	  //Check if the camera module type is OV5642
    	  myCAM.wrSensorReg16_8(0xff, 0x01);
    	  myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
    	  myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
    	  if((vid != 0x56) || (pid != 0x42)){
    		Serial.println(F("Can't find OV5642 module!"));
    		delay(1000);continue;
    	  }
    	  else{
    		Serial.println(F("OV5642 detected."));break;
    	  } 
    	}
    	#endif
    	myCAM.set_format(JPEG);
    	myCAM.InitCAM();
    	#if defined (OV2640_MINI_2MP)
    	  myCAM.OV2640_set_JPEG_size(FRAME_SIZE);
    	#elif defined (OV3640_MINI_3MP)
    	  myCAM.OV3640_set_JPEG_size(OV3640_320x240);
    	#else
    	  myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);   //VSYNC is active HIGH
    	  myCAM.OV5642_set_JPEG_size(OV5642_320x240);
    	#endif
    
    	  delay(1000);
    
    	Video2SD();  
    }
    
    void loop(){
    delay(500000);  
    }

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,673
    Looks interesting - Will have to try it out as my earlier attempts to use this camera failed!

    Looks like I need to look for where this library object is defined: SdFatSdioEX

    It is not located in my Arduino Teensy install nor in my Arduino libraries... The only place I find it in those files is a test program for for ILI9341_t3DMA library...
    Last edited by KurtE; 11-07-2018 at 06:53 PM.

  3. #3
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    100
    It's from SdFat by Bill Greiman. Github written in the code as a comment.

  4. #4
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    100
    Sample video (I know, I'm no Scorsese! )

    https://www.dropbox.com/s/9urc942ons..._n705.avi?dl=0

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,673
    Yep - I have SdFat installed... Turned out I had an older version as well, which was conflicting.

    Still have a compile error, which I will look into:
    It has to do with SPIBUSY and some other constants not not being defined:
    Code:
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp: In member function 'void ArduCAM::setDataBits(uint16_t)':
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3208:28: error: 'SPIMMOSI' was not declared in this scope
    
       const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
    
                                ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3208:40: error: 'SPILMOSI' was not declared in this scope
    
       const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
    
                                            ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3208:53: error: 'SPIMMISO' was not declared in this scope
    
       const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
    
                                                         ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3208:65: error: 'SPILMISO' was not declared in this scope
    
       const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
    
                                                                     ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3210:3: error: 'SPI1U1' was not declared in this scope
    
       SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO)));
    
       ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp: In member function 'void ArduCAM::transferBytes_(uint8_t*, uint8_t*, uint8_t)':
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3214:10: error: 'SPI1CMD' was not declared in this scope
    
       while (SPI1CMD & SPIBUSY) {}
    
              ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3214:20: error: 'SPIBUSY' was not declared in this scope
    
       while (SPI1CMD & SPIBUSY) {}
    
                        ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3219:34: error: 'SPI1W0' was not declared in this scope
    
       volatile uint32_t * fifoPtr = &SPI1W0;
    
                                      ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3237:3: error: 'SPI1CMD' was not declared in this scope
    
       SPI1CMD |= SPIBUSY;
    
       ^
    
    C:\Users\kurte\Documents\Arduino\libraries\ArduCAM\ArduCAM.cpp:3237:14: error: 'SPIBUSY' was not declared in this scope
    
       SPI1CMD |= SPIBUSY;
    
                  ^
    This is in their library code: https://github.com/ArduCAM/Arduino/b...uCAM.cpp#L3214

    It appears like the Teensyduino builds are lumped with esp8266 in the code and all of these defines are in the esp8266 code chain...
    Will create an issue up on github...

  6. #6
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,673
    Actually now that I looking, it appears like you already have an issue opened up there... Also a text file of your changes... Will try applying them and see if it now builds.

  7. #7
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    100
    Mmm that's strange, compiles fine here (Arduino 1.8.7 + TD 1.44 + their library).

    You could try my own patched version of Arducam library:

    https://www.dropbox.com/s/fae8x07it7...M_mod.zip?dl=0

  8. #8
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    100
    Quote Originally Posted by KurtE View Post
    Actually now that I looking, it appears like you already have an issue opened up there... Also a text file of your changes... Will try applying them and see if it now builds.
    I think I've got that patch reversed! First time I've used that Windows diff tool
    You could use the attachment to my previous message (it also supports SPI transactions, which they did not include in their latest version)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •