TTL camera with AltSoftSerial giving no response

Let me backup a little to what lead me to my original post.

I have two adafruit TTL cameras, LCD, Data shield and a few I2C sensors on a mega.
I'm using Arduino IDE 1.0.5

I've tested each camera by themselves and they work. When I attempt to connect both to the mega and run the following code I get.

01 Camera Found:
02 Camera Found:
Failed to get 01 version
--------02 Cam---------
VC0703 1.00
Ctrl infr exist
User-defined sensor
525
Init end

#include <Adafruit_VC0706.h>
#include <SoftwareSerial.h>         

//Weather proof goes by the following
//Green RX
//White is TX

SoftwareSerial cameraconnection_01 = SoftwareSerial(50, 15); 
Adafruit_VC0706 cam_01 = Adafruit_VC0706(&cameraconnection_01);

SoftwareSerial cameraconnection_02 = SoftwareSerial(51, 17);
Adafruit_VC0706 cam_02 = Adafruit_VC0706(&cameraconnection_02);


void setup() {

  Serial.begin(9600);
   // Try to locate the camera
  if (cam_01.begin()) {
    Serial.println("01 Camera Found:");
  } else {
    Serial.println("No 01 camera found?");
  }
  if (cam_02.begin()) {
    Serial.println("02 Camera Found:");
  } else {
    Serial.println("No 02 camera found?");
  }  
  
  // Print out the camera version information
  char *reply = cam_01.getVersion();
  if (reply == 0) {
    Serial.println("Failed to get 01 version");
  } else {
    Serial.println("-------01 Cam----------");
    Serial.print(reply);
    Serial.println("-----------------");
  }
    // Print out the camera version information
  reply = cam_02.getVersion();
  if (reply == 0) {
    Serial.println("Failed to get 02 version");
  } else {
    Serial.println("--------02 Cam---------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

}

void loop() {
 

}

At this point, I was advised SoftwareSerial "If using multiple software serial ports, only one can receive data at a time." or 'able to communicate'.

So I tried AltSoftSerial as I noted in my first post.

So how about you give it a go now with hardware serial and see how it goes.

When I replace SoftwareSerial in the above code with HardwareSerial I get a compile error "no matching function for call to 'HardwareSerial::HardwareSerial(int, int)'

OK bear with me I'll download the adafruit library and see if I can get to the bottom of it.

OK Well I've found that the library files are absolutely riddled with unreasonable dependencies on software serial. Even though there needn't be.

I've done some pretty extensive editing and managed to get your example to compile against my version of the Adafruit_VC0706.h library. I have no hardware to test this on though.

If you'd like to try this out I'll upload the library files (and your modified sketch) here for you to try.

OK Well I've found that the library files are absolutely riddled with unreasonable dependencies on software serial. Even though there needn't be.

I suspect that, like the Arduino process, Adafruit accepts libraries from less-than-professional programmers. I find it difficult to believe that, as good as their products and libraries usually are, that they developed this library that way.

It was nice of you to investigate, and develop a fix. How are you removing the dependency? By having the user provide the soft or hard serial instance to use?

PaulS:
It was nice of you to investigate, and develop a fix. How are you removing the dependency? By having the user provide the soft or hard serial instance to use?

I''m not sure that my solution is the ideal. It does mean that using a mega2560, it will remove any option of using softwareSerial.

Here's just one example of what I mean about the unnecessary dependency issue. When this runs, if you're using hardwareSerial, all should all be well EXCEPT it just won't compile unless you have the softwareSerial library present. (this is exactly as it comes)

void Adafruit_VC0706::sendCommand(uint8_t cmd, uint8_t args[] = 0, uint8_t argn = 0) {
  if(swSerial) {
#if ARDUINO >= 100
    swSerial->write((byte)0x56);
    swSerial->write((byte)serialNum);
    swSerial->write((byte)cmd);

    for (uint8_t i=0; i<argn; i++) {
      swSerial->write((byte)args[i]);
      //Serial.print(" 0x");
      //Serial.print(args[i], HEX);
    }
#else
    swSerial->print(0x56, BYTE);
    swSerial->print(serialNum, BYTE);
    swSerial->print(cmd, BYTE);

    for (uint8_t i=0; i<argn; i++) {
      swSerial->print(args[i], BYTE);
      //Serial.print(" 0x");
      //Serial.print(args[i], HEX);
    }
#endif
  } else {
#if ARDUINO >= 100
    hwSerial->write((byte)0x56);
    hwSerial->write((byte)serialNum);
    hwSerial->write((byte)cmd);

    for (uint8_t i=0; i<argn; i++) {
      hwSerial->write((byte)args[i]);
      //Serial.print(" 0x");
      //Serial.print(args[i], HEX);
    }
#else
    hwSerial->print(0x56, BYTE);
    hwSerial->print(serialNum, BYTE);
    hwSerial->print(cmd, BYTE);

    for (uint8_t i=0; i<argn; i++) {
      hwSerial->print(args[i], BYTE);
      //Serial.print(" 0x");
      //Serial.print(args[i], HEX);
    }
#endif
  }
}

So for this I've just added in front of it

#if defined(__AVR_ATmega2560__)
void Adafruit_VC0706::sendCommand(uint8_t cmd, uint8_t args[] = 0, uint8_t argn = 0) {

hwSerial->write((byte)0x56);
hwSerial->write((byte)serialNum);
    hwSerial->write((byte)cmd);
    for (uint8_t i=0; i<argn; i++) {
      hwSerial->write((byte)args[i]);
    }
}
#else ....

Personally, if I had more time to work on it, I'd be inclined to make an abstract class to handle the serial and make the rest of the library much cleaner. This would make it easier to include or leave out the softwareSerial as the user sees fit.

I'd be inclined to make an abstract class to handle the serial and make the rest of the library much cleaner.

Both HardwareSerial and SoftwareSerial derive from Stream, and provide the same functionality (though in very different ways). If the Adafruit_VC0706 class to a pointer to the instance of HardwareSerial or SoftwareSerial to write to, it would not be necessary to know which derived class the pointer pointed to.

KenF:
I've done some pretty extensive editing and managed to get your example to compile against my version of the Adafruit_VC0706.h library. I have no hardware to test this on though.

If you'd like to try this out I'll upload the library files (and your modified sketch) here for you to try.

KenF Wow I'm grateful for your time and effort! Absolutely I'd like to try the updated files and sample sketch.
At the end of the day, this is for a middle school science project using Infragram.org 'infrablue' images on one camera and standard color images on a second camera.

Bucky99:
KenF Wow I'm grateful for your time and effort! Absolutely I'd like to try the updated files and sample sketch.
At the end of the day, this is for a middle school science project using Infragram.org 'infrablue' images on one camera and standard color images on a second camera.

OK. I've also made copies of the examples that came with the original libraries. modified to work with the mega. (using serial only)

Bear with me, I'll Just rename the library files zip them up and find somewhere to upload. But like I say, I haven't got any hardware to test this on.

PaulS:
Both HardwareSerial and SoftwareSerial derive from Stream, and provide the same functionality (though in very different ways). If the Adafruit_VC0706 class to a pointer to the instance of HardwareSerial or SoftwareSerial to write to, it would not be necessary to know which derived class the pointer pointed to.

This is my thoughts exactly. Unfortunately, as it stands, there are three different constructors. They all include pointers to different types. A bit of cross casting, with perhaps an extra parameter to denote the actual type being passed, could overcome the issue.

Maybe later.

KenF:
Bear with me, I'll Just rename the library files zip them up and find somewhere to upload. But like I say, I haven't got any hardware to test this on.

No Problem - I'll test - I have the hardware to test on.

OK Here are the modded library files. I've renamed them MegaVC0706 so that you can keep your existing libraries without any conflict.

If you install them properly, you should be able to find the examples from the IDE MEGAMotionDetect and MEGASnapshot.

MegaVC0706.zip (12.1 KB)

By the way, you realise you'll have to use the pins that are used for the Serial1 (instead of your software serial ones) Serial 1 uses pin 18 for tx pin 19 for rx

Here's the example code you posted earlier with the modifications to suit.

#include <MegaVC0706.h>
#include <SD.h>

Adafruit_VC0706 cam_01 = Adafruit_VC0706(&Serial1);  //Pin 18 TX  Pin 19= RX
Adafruit_VC0706 cam_02 = Adafruit_VC0706(&Serial2);  //Pin 16 TX  Pin 17= RX
#define chipSelect 53

void setup() {
pinMode(chipSelect, OUTPUT); // SS 

  Serial.begin(9600);
   // Try to locate the camera
  if (cam_01.begin()) {
    Serial.println("01 Camera Found:");
  } else {
    Serial.println("No 01 camera found?");
  }
  if (cam_02.begin()) {
    Serial.println("02 Camera Found:");
  } else {
    Serial.println("No 02 camera found?");
  }  
  
  // Print out the camera version information
  char *reply = cam_01.getVersion();
  if (reply == 0) {
    Serial.println("Failed to get 01 version");
  } else {
    Serial.println("-------01 Cam----------");
    Serial.print(reply);
    Serial.println("-----------------");
  }
    // Print out the camera version information
  reply = cam_02.getVersion();
  if (reply == 0) {
    Serial.println("Failed to get 02 version");
  } else {
    Serial.println("--------02 Cam---------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

}

void loop() {
}

SUCCESS Wow Wow Wow :smiley:

Here's my Hacked version of your MEGASnapShot sample with two Camera connections using the hardware Serial. Tested and Saving pictures to the SD! I know the Picture taking code (copy/paste) is not optimal but it works.

Thank you KenF! Let the Algae growth begin! LOL

#include <MegaVC0706.h>
#include <SD.h>

#define chipSelect 10
Adafruit_VC0706 cam_01 = Adafruit_VC0706(&Serial1);
Adafruit_VC0706 cam_02 = Adafruit_VC0706(&Serial2);

void setup() {

  // When using hardware SPI, the SS pin MUST be set to an
  // output (even if not connected or used).  If left as a
  // floating input w/SPI on, this can cause lockuppage.
pinMode(53, OUTPUT); // SS on Mega

Serial.begin(9600);
Serial.println("VC0706 Camera snapshot test");
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }  
  
  // Try to locate the camera
  if (cam_01.begin()) {
    Serial.println("Camera 1 Found:");
  } else {
    Serial.println("No camera 1 found?");
    return;
  }
    // Try to locate the camera
  if (cam_02.begin()) {
    Serial.println("Camera 2 Found:");
  } else {
    Serial.println("No camera 2 found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam_01.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get 1 version");
  } else {
    Serial.println("--------1---------");
    Serial.print(reply);
    Serial.println("-----------------");
  }
  // Print out the camera version information (optional)
  reply = cam_02.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get 2 version");
  } else {
    Serial.println("-------2 ----------");
    Serial.print(reply);
    Serial.println("-----------------");
  }
  // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 
  // Remember that bigger pictures take longer to transmit!
  
  cam_01.setImageSize(VC0706_640x480);        // biggest
  cam_02.setImageSize(VC0706_640x480);        // biggest  

}

void loop() {
    Serial.println("Snap Cam_01 in 3 secs...");
  delay(3000);

  if (! cam_01.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam_01.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

  int32_t time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam_01.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");
  
  
  
  
  Serial.println("Snap Cam_02 in 3 secs...");
  delay(3000);

  if (! cam_02.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
//  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
//  File imgFile = SD.open(filename, FILE_WRITE);
    imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
//  uint16_t jpglen = cam_02.frameLength();
  jpglen = cam_02.frameLength();  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

//  int32_t time = millis();
  time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
//  byte wCount = 0; // For counting # of writes
  wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam_02.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");  
  delay(60000);
}

KenF:
By the way, you realise you'll have to use the pins that are used for the Serial1 (instead of your software serial ones) Serial 1 uses pin 18 for tx pin 19 for rx

Yes, Thank your for checking!

Brilliant. The hardware serial should be more reliable than the software varieties anyhow. How many cameras are you likely to be using at any one time? Obviously you realise there's still Serial3 and even plain Serial can be used.

As it stands, on a mega2560, this library won't work with software serial any more. With a bit of effort, I could probably rectify that, but would it be worth it?

Opps The above code will not take additional pictures without .resumeVideo(); at the end of each picture.

KenF:
How many cameras are you likely to be using at any one time? Obviously you realise there's still Serial3 and even plain Serial can be used.

As it stands, on a mega2560, this library won't work with software serial any more. With a bit of effort, I could probably rectify that, but would it be worth it?

This project only requires two cameras, one with a blue filter and one standard. Yes I realize I still have two more Serial that can be used.

So far I do not see any reason to fix software serial for this MegaVC0706 library. It will work with up to 4 hardware serial connections. Which is two more than I need with this project.

Many Many Thanks KenF!

Hi all,

I've followed this thread and have attempted to implement changes to the code such that the Arduino Due is supported.

Is it possible? Everytime I run the compiler, it hangs up and doesn't finish. I don't know what to do.

Changes I made:

replaced defined(AVR_ATmega2560) with defined(SAM3X8E)
Using Serial1 on the Due, which corresponds to pins 18 and 19.

Here is the verbose white text that spits back at me before it hangs there:

Using library SD in folder: C:\Program Files (x86)\Arduino\libraries\SD 

C:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++ -c -g -Os -Wall -Wextra -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -MMD -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=10604 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/libsam -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/CMSIS/Include/ -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/Device/ATMEL/ -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\cores\arduino -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\variants\arduino_due_x -IC:\Program Files (x86)\Arduino\libraries\SD\src C:\Users\Mahdie\AppData\Local\Temp\build6636715804119919100.tmp\DUE_Proj3.cpp -o C:\Users\Mahdie\AppData\Local\Temp\build6636715804119919100.tmp\DUE_Proj3.cpp.o 
C:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++ -c -g -Os -Wall -Wextra -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -MMD -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=10604 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/libsam -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/CMSIS/Include/ -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/Device/ATMEL/ -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\cores\arduino -IC:\Users\Mahdie\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\variants\arduino_due_x -IC:\Program Files (x86)\Arduino\libraries\SD\src C:\Users\Mahdie\AppData\Local\Temp\build6636715804119919100.tmp\Due_VC0706.cpp -o C:\Users\Mahdie\AppData\Local\Temp\build6636715804119919100.tmp\Due_VC0706.cpp.o