Using SoftwareSerial inside a library - Arduino 1.02

I had a similar problem a while back but with the serial port. PaulS helped me out.

Have a look at this:

http://arduino.cc/forum/index.php/topic,40435.0.html

I haven't tried it but the same principles should apply to the software serial.

Thanks guys, still cant get it working.

Here is a better layout of what I have currently, if you can point out what I have done wrong I would appreciate it.
I have little knowledge at all of C++.

So as mentioned above, I am just trying to get my library to be able to use the Software Serial, my sketch does not need access to it. But if it has to, then that is fine...

Library.h File

#ifndef Library_h
#define Library_h
 
#include "Arduino.h" // for Arduino 1.0

#include <SoftwareSerial.h> //Software Serial Library

class Library
{
	public:
		//Bunch of stuff here
	
	private:
		SoftwareSerial mySerial;
}

Library.cpp File

#include "Library.h"
#include "Arduino.h" // for Arduino 1.0

mySerial = SoftwareSerial(2, 3); //Tried various combinations, in and out of the constructor, but similar results.

Library::Library()  
{
	mySerial.begin(9600);
}

My Sketch

#include <SoftwareSerial.h>
#include <Library.h>

Library Library;

void Setup()
{
	
}

void loop()
{
}

The above might not be the best combination I have tried, but is one of them.
Really not sure what I am doing, so help would be apprecaited.

Thanks
J

You need to construct the SoftwareSerial instance at the same time you construct the class:

Library::Library() , mySerial(2,3)

Sorry so that goes in the cpp file?

So the h file and the sketch looks ok...?

But the cpp file needs to be this?:

#include "Library.h"
#include "Arduino.h" // for Arduino 1.0

Library::Library()  
{
	 mySerial(2,3);
	 mySerial.begin(9600);
}

not sure sure what Library::Library() , mySerial(2,3) means... is that a single line I put in place of the Library::Library() ?

Im getting a truck load of errors...

error: ISO C++ forbids declaration of 'Library' with no type
error: no 'int Library::Library()' member function declared in class 'Library'
etc

Sorry can you spell it out for me...
Thanks

made a typo which didnt help, in the Library::Library() line.

Errors I get now are:

Library.cpp: In constructor 'Library::Library()':
Library.cpp:13: error: no matching function for call to 'SoftwareSerial::SoftwareSerial()'
SoftwareSerial.h:83: note: candidates are: SoftwareSerial::SoftwareSerial(uint8_t, uint8_t, bool)
SoftwareSerial.h:48: note: SoftwareSerial::SoftwareSerial(const SoftwareSerial&)
Library.cpp:15: error: no match for call to '(SoftwareSerial) (int, int)'

Line 13 is:

Library::Library() //Line 13
{
	mySerial(2, 3);
	mySerial.begin(9600);
}

PaulS:
You need to construct the SoftwareSerial instance at the same time you construct the class:

Library::Library() , mySerial(2,3)

Probably a typo, sholuld be (in the cpp file):

Library::Library() : mySerial(2,3) {
    // code
}

Yep thats seems to be better, thanks.

I get past this bit now, got more errors related my other code now I think.

Thanks

If Class has member objects, its constructor takes this general form:

Class::Class() : obj1(...), obj2(...), ... {
// Class instance construction code
}

I know this is an old post, hopefully it pops up somewhere. I'm trying to implement the same concept but I don't understand what I'm doing wrong.

I want to run an instance of softwareserial in the library files, the error I'm running into though is

ISO C++ forbids declaration of 'SoftwareSerial' with no type

The line it refers to is

private:
SoftwareSerial *SSerial;

in my header file.

I attempted the change mentioned by PaulS where I instantiate the softwareserial when I create the constructor

Library::Library(): SSerial(4,5)
{

}

I've looked at examples and tried to match them, my first attempt everything worked properly except when I was trying to retrieve data using SSerial.available() and SSerial.read()

My code works fine without the software serial on the standard TX/RX pins, so what I'm trying to narrow down is what exactly do I need to place into my .h and .cpp files to have the software serial functioning properly.

My code works fine without the software serial on the standard TX/RX pins

Please explain this. You can NOT do software serial on the hardware serial pins.

http://snippets-r-us.com might be able to help you with the snippets. Here, we need to see ALL of your code.

PaulS:

My code works fine without the software serial on the standard TX/RX pins

Please explain this. You can NOT do software serial on the hardware serial pins.

http://snippets-r-us.com might be able to help you with the snippets. Here, we need to see ALL of your code.

What I mean by this is without implementing any type of softwareserial the code executes successfully, my problem is I have plans for the Pin 1 and Pin 0 so I have to move my device from pins 1/0 which is why I'm trying to implement the software serial to move them to pins 4,5. The snippets link isn't working for me, perhaps you know another link?

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.

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.

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

#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;
}

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

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_

In CameraC329.h, you have:

	SoftwareSerial *camSerial;

without providing the compiler a clue as to what a SoftwareSerial is. How much clearer can the message be?

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.

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

PaulS:

but can't find any NewSofSerial on CameraC328r.cpp and CameraC328r.H ?

Perhaps you should try NewSoftSerial, then:

class NewSoftSerial;
CameraC328R(NewSoftSerial *softSerial = NULL);
NewSoftSerial *_serialPort;

#include <NewSoftSerial.h>
CameraC328R::CameraC328R(NewSoftSerial *softSerial)

So I Modified mine to

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

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

to

CameraC329::CameraC329(SoftwareSerial *softSerial)
{
  _serialPort = softSerial;
 }

And in the sketch I changed it to use

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)

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?

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.