Pages: 1 [2]   Go Down
Author Topic: Using SoftwareSerial inside a library - Arduino 1.02  (Read 2290 times)
0 Members and 1 Guest are viewing this topic.
Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The snippets link isn't working for me, perhaps you know another link?
That was a clue-by-4. You were supposed to whack yourself with it, and post ALL of your code.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is all code from a repository I was using for the camera I'm working with, the only changes from the original code is I made the changes so that it would work in Arduino 1.0+. This is my last attempt to make the changes to use software serial, I tried to imitate some of the changes from someones project called "MeetAndroid" if I can dig up that link I'll link that as well.
I don't know if you'd like to see the sketch as well but as of right now I had a boat load of errors and I managed to work through them and I'm down to this last one which I've been looking and I can't seem to fix it properly.

Code:
In file included from sketch_apr02a.ino:2:
C:\...\arduino-1.0.4\libraries\CameraC329/CameraC329.h:117: error: ISO C++ forbids declaration of 'SoftwareSerial' with no type
C:\...\arduino-1.0.4\libraries\CameraC329/CameraC329.h:117: error: expected ';' before '*' token
CameraC329.CPP
Code:
#include "CameraC329.h"
#include <SoftwareSerial.h>
#
//-----------------------------------------------------------------------------
//
// Constants
//
//-----------------------------------------------------------------------------

static const byte CMD_PREFIX = 0xFF;
static const byte CMD_INITIAL = 0x01;
static const byte CMD_GETPICTURE = 0x04;
static const byte CMD_SNAPSHOT = 0x05;
static const byte CMD_RESET = 0x08;
static const byte CMD_POWEROFF = 0x09;
static const byte CMD_DATA = 0x0A;
static const byte CMD_SYNC = 0x0D;
static const byte CMD_ACK = 0x0E;
static const byte CMD_NAK = 0x0F;
static const byte CMD_QUALITY = 0x10;
static const byte ZERO = 0x00;

/**
 * Constructor
 */
SoftwareSerial* camSerial;
CameraC329::CameraC329(uint16_t baudrate, uint8_t rxpin, uint8_t txpin)
{
    camSerial = new SoftwareSerial(rxpin, txpin);
    camSerial->begin(baudrate);

}


/**
 * Synchronize with the camera. Synchronization will be attempted up to
 * MAX_SYNC_ATTEMPTS. You must synchronize with the camera before you can
 * call other methods.
 *
 * @return True if successful, false otherwise.
 */
bool CameraC329::sync()
{
  uint8_t syncAttempts = 0;
  bool success = false;

  setOutputCommand(CMD_SYNC, ZERO, ZERO, ZERO, ZERO);

  while (syncAttempts < MAX_SYNC_ATTEMPTS)
  {
    sendCommand();

    // Wait for ACK response
    success = waitForACK(RESPONSE_DELAY, CMD_SYNC);

    // Make sure it is an ACK
    if (success)
    {
      // Now wait for SYNC from camera
      success = waitForResponse(RESPONSE_DELAY);
      if (success && inputCommand[3] == CMD_SYNC)
      {
        // All is good, flush the buffer
        camSerial.flush();

        // Send ACK
        setOutputCommand(CMD_ACK, CMD_SYNC, ZERO, ZERO, ZERO);
        sendCommand();

        return true;
      }
    }

    syncAttempts++;
  }

  return false;
}

/**
 * Sets the camera's initial baud rate, color type, and image sizes. Call this
 * method after synchronization to set up appropriate parameters before
 * taking a snapshot.
 *
 * @param baudRate The baud rate to use for future camera communication
 * @param colorType The color type
 * @param previewResolution The preview resolution
 * @param jpegResolution The JPEG resolution
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::initialize(BaudRate baudRate, ColorType colorType,
    PreviewResolution previewResolution, JPEGResolution jpegResolution)
{
  setOutputCommand(CMD_INITIAL, baudRate, colorType, previewResolution,
    jpegResolution);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_INITIAL))
    return true;

  return false;
}

/**
 * Set the quality level for compressed (JPEG) images.
 *
 * @param qualityLevel The desired quality level. Should be a value from the
 * QualityLevel enumeration.
 */
bool CameraC329::setQuality(QualityLevel qualityLevel)
{
  setOutputCommand(CMD_QUALITY, qualityLevel, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_QUALITY))
    return true;

  return false;
}

/**
 * Takes a snapshot with the camera and stores it in the camera's internal
 * data buffer. Once a snapshot has been taken, use getPicture to retrieve
 * the photo data.
 *
 * @param pictureType The picture type to take. Should be a value from the
 * PictureType enumeration.
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::takeSnapshot(PictureType pictureType)
{
  setOutputCommand(CMD_SNAPSHOT, pictureType, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_SNAPSHOT))
    return true;

  return false;
}

bool CameraC329::getPicture(PictureType pictureType, void (*callback)(uint32_t pictureSize, uint16_t packetSize, uint32_t packetStartPosition, byte* packet))
{
  uint32_t pictureSize = 0;

  setOutputCommand(CMD_GETPICTURE, pictureType, ZERO, ZERO, ZERO);
  sendCommand();

  if (!waitForACK(RESPONSE_DELAY, CMD_GETPICTURE))
    return false;

  if (!(waitForResponse(RESPONSE_DELAY) && inputCommand[3] == CMD_DATA))
    return false;

  pictureSize = inputCommand[7] << 8;
  pictureSize |= inputCommand[6] << 8;
  pictureSize |= inputCommand[5];

  uint32_t bytePosition = 0;
  uint8_t package[DEFAULT_PACKAGE_SIZE];

  while (bytePosition < pictureSize)
  {
    if (!waitForResponse(RESPONSE_DELAY, package, DEFAULT_PACKAGE_SIZE))
      return false;

    callback(pictureSize, min(DEFAULT_PACKAGE_SIZE, pictureSize - bytePosition), bytePosition, package);
    bytePosition += DEFAULT_PACKAGE_SIZE;
  }

  return true;
}

/**
 * Resets the camera.
 *
 * @param resetType The type of reset to perform (ether a "soft" reset which
 * resets only the camera's internal state machine) or a "hard" reset.
 *
 * @return True if successful, false otherwise.
 */
bool CameraC329::reset(ResetType resetType)
{
  setOutputCommand(CMD_RESET, resetType, ZERO, ZERO, 0xFF);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_RESET))
    return true;

  return false;
}

/**
 * Power off the camera. The camera will be unusable after calling this method
 * until a successful re-synchronization.
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::powerOff()
{
  setOutputCommand(CMD_POWEROFF, ZERO, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_POWEROFF))
    return true;

  return false;
}

/**
 * @private
 *
 * Sends the command that is in the outputCommand buffer. Command bytes are
 * sent in big endian order.
 */
void CameraC329::sendCommand()
{
  uint8_t i;

  // Big endian
  for (i = 0; i < CMD_SIZE; i++)
  {
    camSerial.write((byte)outputCommand[i]);
  }
}

bool CameraC329::waitForACK(uint32_t timeout, uint8_t cmd)
{
  bool success = waitForResponse(timeout);

  if (success && inputCommand[3] == CMD_ACK && inputCommand[4] == cmd)
    return true;

  return false;
}

/**
 * @private
 *
 * Waits for a response up to timeout, and stores the response in the
 * inputCommand array.
 *
 * @return True if response is received before the timeout, false otherwise.
 */
bool CameraC329::waitForResponse(uint32_t timeout)
{
  return waitForResponse(timeout, inputCommand, CMD_SIZE);
}

/**
 * @private
 *
 * Waits for a response up to timeout, and stores the response in the buffer
 * array provided.
 *
 * @param timeout The timeout
 * @param buffer The buffer within which to store the response
 * @param bufferLength The length of the provided buffer
 *
 * @return True if response is received before timeout, false otherwise
 */
bool CameraC329::waitForResponse(uint32_t timeout, byte buffer[], uint16_t bufferLength)
{
  uint8_t byteCount = 0;
  unsigned long time = millis();

  while (millis() - time <= timeout)
  {
    while (camSerial.available() > 0)
    {
      buffer[byteCount] = camSerial.read();
      byteCount++;

      if (byteCount == bufferLength)
        return true;
    }
  }

  if (byteCount > 0)
    return true;

  return false;
}

/**
 * @private
 *
 * Utility method for populating the output command buffer.
 */
void CameraC329::setOutputCommand(const byte command, byte param1, byte param2, byte param3, byte param4)
{
  outputCommand[0] = CMD_PREFIX;
  outputCommand[1] = CMD_PREFIX;
  outputCommand[2] = CMD_PREFIX;
  outputCommand[3] = command;
  outputCommand[4] = param1;
  outputCommand[5] = param2;
  outputCommand[6] = param3;
  outputCommand[7] = param4;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is everything, sorry for the double post. Oh and the only difference between my attempt at this and the original user as far as software goes is I'm using 1.04
Code:
CameraC329.H
#ifndef CAMERAC329_H_
#define CAMERAC329_H_

#include "Arduino.h"
#include <inttypes.h>

// The byte size of UART commands
#define CMD_SIZE 8

// Number of sync attempts to try before giving up
#define MAX_SYNC_ATTEMPTS 60

// How long to wait for serial communication responses
#define RESPONSE_DELAY 100

// Size (in bytes) to split up picture data into packages for processing
#define DEFAULT_PACKAGE_SIZE 64

class CameraC329
{
  public:
    enum BaudRate
    {
      BAUD7200 = 0x08,
      BAUD14400 = 0x07,
      BAUD28800 = 0x06,
      BAUD57600 = 0x05,
      BAUD115200 = 0x04,
      BAUD230400 = 0x03,
      BAUD460800 = 0x02,
      BAUD921600 = 0x01
    };

    enum ColorType
    {
      CT_Y4 = 0x02,
      CT_Y8 = 0x03,
      CT_RGB12 = 0x05,
      CT_RGB16 = 0x06,
      CT_RGB24 = 0x08,
      CT_YUV16 = 0x09,
      CT_JPEG = 0x07
    };

    enum PreviewResolution
    {
      PR_80x60 = 0x01,
      PR_88x72 = 0x02,
      PR_160x120 = 0x03,
      PR_176x144 = 0x04,
      PR_320x240 = 0x05,
      PR_352x288 = 0x06,
      PR_640x480 = 0x07,
      PR_80x64 = 0x08,
      PR_128x96 = 0x09,
      PR_128x128 = 0x0A,
      PR_160x128 = 0x0B
    };

    enum JPEGResolution
    {
      JR_80x60 = 0x01,
      JR_88x72 = 0x02,
      JR_160x120 = 0x03,
      JR_176x144 = 0x04,
      JR_320x240 = 0x05,
      JR_352x288 = 0x06,
      JR_640x480 = 0x07,
      JR_80x64 = 0x08,
      JR_128x96 = 0x09,
      JR_128x128 = 0x0A,
      JR_160x128 = 0x0B
    };

    enum PictureType
    {
      PT_SNAPSHOT = 0x01,
      PT_PREVIEW = 0x02,
      PT_SERIAL_FLASH = 0x03,
      PT_JPEG_PREVIEW = 0x05,
      PT_PLAYBACK = 0x06
    };

    enum DataType
    {
      DT_REGISTER = 0x00,
      DT_SNAPSHOT = 0x01,
      DT_PREVIEW = 0x02,
      DT_JPEG_PREVIEW = 0x04,
      DT_PLAYBACK = 0x05
    };

    enum ResetType
    {
      RT_ALL = 0x00,
      RT_STATE = 0x01
    };

    enum QualityLevel
    {
      QL_BEST = 0x00,
      QL_BETTER = 0x01,
      QL_NORMAL = 0x02
    };

    CameraC329(uint16_t baudrate, uint8_t rxpin, uint8_t txpin);
    bool sync();
    bool initialize(BaudRate, ColorType, PreviewResolution, JPEGResolution);
    bool setQuality(QualityLevel);
    bool takeSnapshot(PictureType);
    bool getPicture(PictureType, void (*)(uint32_t, uint16_t, uint32_t, byte*));
    bool reset(ResetType);
    bool powerOff();


  private:
SoftwareSerial *camSerial;
    byte outputCommand[CMD_SIZE];
    byte inputCommand[CMD_SIZE];
    void sendCommand();
    bool waitForACK(uint32_t, uint8_t);
    bool waitForResponse(uint32_t);
    bool waitForResponse(uint32_t, byte[], uint16_t);
    void setOutputCommand(const byte, byte, byte, byte, byte);
};

#endif // CAMERAC329_H_
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In CameraC329.h, you have:
Code:
SoftwareSerial *camSerial;
without providing the compiler a clue as to what a SoftwareSerial is. How much clearer can the message be?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok sorry I'm still a novice at this. However I did include the SoftwareSerial.h before and it gave me the same error message. I'm not sure if thats what you're referring to though.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 I was combing through the forums and I found an old post where you mentioned

Quote
but can't find any NewSofSerial on CameraC328r.cpp and CameraC328r.H ?
Perhaps you should try NewSoftSerial, then:
Code:
class NewSoftSerial;
CameraC328R(NewSoftSerial *softSerial = NULL);
NewSoftSerial *_serialPort;
#include <NewSoftSerial.h>
CameraC328R::CameraC328R(NewSoftSerial *softSerial)
So I Modified mine to

Code:
class SoftwareSerial;
CameraC329(SoftwareSerial *softSerial = NULL);
SoftwareSerial *_serialPort;
#include <SoftwareSerial.h>
CameraC329::CameraC329(SoftwareSerial *softSerial)

I made the associated changes for the C329 and the code compiled, the only issue now is the camera is syncing and it seems the SoftwareSerial is functioning properly but it's failing to get a picture. The key major changes I made were in the constructor for the camera I changed it from
Code:
CameraC329::CameraC329(uint16_t baudrate, uint8_t rxpin, uint8_t txpin)
{
    camSerial = new SoftwareSerial(rxpin, txpin);
    camSerial->begin(baudrate);

}
to
Code:
CameraC329::CameraC329(SoftwareSerial *softSerial)
{
  _serialPort = softSerial;
 }
And in the sketch I changed it to use
Code:
SoftwareSerial mySerial(2, 3);
CameraC329 camera(&mySerial);
I changed all the camSerial.write/flush/available/read to _serialPort->write/flush/available/read and the proposed change you mentioned above in my header files. I'm still not sure why when I use the regular Hardware serial I get a picture but when I'm using this softwareserial I can't.

(BTW I'm sorry if this is no longer the topic for this thread, I'm not sure if I should make a new thread for this because Now my issue as far as implementing SoftwareSerial is semi-solved)
« Last Edit: April 03, 2013, 09:36:36 pm by Sweepstar » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm still not sure why when I use the regular Hardware serial I get a picture but when I'm using this softwareserial I can't.
Do you have the camera connected to pins 2 and 3? What is happening on those pins?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, I have the TX line from the camera connected to pin 2 and the RX line connected to pin 3 to establish a TX/RX connection between the camera and arduino. Most operations work, I get like 80% functionality using the softwareserial changes I just can't get a picture. But I do sync the camera to the arduino, I can initialize the camera through the arduino, I can reset the camera through arduino just can't get the picture when I'm using softwareserial implementation.

This is the physical connection I'm using, only difference is I'm using 33k and 10k resistors for the voltage divider on the C329 camera.
« Last Edit: April 04, 2013, 11:46:06 am by Sweepstar » Logged

Pages: 1 [2]   Go Up
Jump to: