Pages: [1]   Go Down
Author Topic: Malloc? Dynamic array.  (Read 2689 times)
0 Members and 1 Guest are viewing this topic.
Canada
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
I Love Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, started trying to make libraries for Arduino. I am a C/C++ beginner. Got a metronome class going, will post soon. Now working on a message parser. I wanted to create a dynamic buffer (so the user could select how much memory to allocate to the parser), I tried "new", but got strange errors. I then tried malloc but the Arduino would not work (would get stuck in boot mode).
Can I use malloc on a microcontroller?

Another question: Is a library recompiled everytime I compile a sketch that uses it? If so I could use a define to let the user determine the buffer size.

Here is my code. It's the last version that does not use malloc or new. How can I make the message[] dynamic in size (instead of always 32)

Message.h
Code:
#ifndef Message_h
#define Message_h

#include "WConstants.h"



class Message
{

public:
  Message();
  char complete(); //reads the serial buffer and returns 1 if the message is complete(terminated by a carriage return) or 0 if not)
  char checkword(const char * string_to_compare); //compare the current word to a sting (each word is terminated by a space or the end of the message)
  char nextword(); //get the next word
  int wordtoint(); //convert the word to an integer

private:
  char *last;
  char message[32];
  int messageindex;
  char serialbyte;
  char *word;
  int buffersize;
  

};

#endif



Message.cpp
Code:
#include "WProgram.h"
#include "Message.h"
#include "HardwareSerial.h"
#include "string.h"


Message::Message()
{
        buffersize = 32;
      messageindex = 0;
}

char Message::complete()
{
   while (Serial.available() > 0) {
    
      serialbyte = Serial.read();
      
      if (serialbyte == 13) {
         message[messageindex]=0;
         messageindex=0;
         word = strtok_r(message," ",&last);
          if (word == NULL) return 0;
         return 1;
        
      } else {
        
        if (serialbyte == 10) return 0;
        
         message[messageindex]=serialbyte;
         messageindex++;
         if (messageindex >= buffersize) messageindex = 0;
      }
      
  }
  return 0;
}

char Message::checkword(const char * string_to_compare)
{
      if (strcmp(word,string_to_compare) == 0) return 1 ;
    return 0;
}

char Message::nextword()
{

    word = strtok_r(NULL," ",&last);
    if (word == NULL) return 0;
    return 1;
}

int Message::wordtoint()
{

    return atoi(word);
}


/*
class Message
{

public:
  Message(int buffer_size);
  
  char complete(); //reads the serial buffer and returns 1 if the message is complete(terminated by a carriage return) or 0 if not)
  char checkword(const char * string_to_compare); //compare the current word to a sting (each word is terminated by a space or the end of the message)
  char nextword(); //get the next word
  int wordtoint(); //convert the word to an integer

private:
  char *last;
  char message[];
  int messageindex;
  char serialbyte;
  

}; */
Logged

Thomas Ouellet Fredericks

Canada
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
I Love Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is an example:

Code:
#include <Message.h>

Message myMessage = Message();

void setup()
{
  Serial.begin(9600);

}

void loop()
{
 
  if (myMessage.complete()) {
    if (myMessage.checkword("hi")) Serial.println("hello");
    if (myMessage.checkword("bye")) Serial.println("Bye to you too");
  }

}
Logged

Thomas Ouellet Fredericks

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you really need to send such verbose messages (e.g. multiple words)?  It's an interesting thing to try to get working, but probably not the best idea for a microcontroller with limited RAM and program space.  In any case, I think malloc() should work, though I haven't tried it yet.  Can you post the version of the code that uses it?
Logged

Canada
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
I Love Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The commands do not have to be verbose. I just needead a failsafe way of sending integers and keeping the whole thing synched (I do not want the ascii codes getting mixed up with the raw numbers for example).

You can send commands as :
s 5 1506 /r
When the microcontroller receives the carriage return, it automatically parses the command which could translate into: treat pin 5 as a servo controller with a pulse of 1506 ms.

Here is my latest code. I am getting some very strange errors (copied from the Arduino IDE):
In file included from /SerialInMessage.h:6,
                 from SerialInMessage.cpp:3:
C:/Documents and Settings/maude/Mes documents/tom/arduino-0004/lib/targets/arduino/WConstants.h:1:20: warning: no newline at end of file
SerialInMessage.cpp: In member function 'char SerialInMessage::complete()':
SerialInMessage.cpp:22: warning: comparison is always true due to limited range of data type


Whay does that mean? I am comparing a char with the number 128? It should not be out of range!
The library and the example code compile but the Arduino does not run the code (stalls in boot mode).

Here is SerialInMessage.h

Code:

#ifndef SerialInMessage_h
#define SerialInMessage_h

#include "WConstants.h"


class SerialInMessage
{

public:
  SerialInMessage(int SIM_buffer_size);
  char complete(); //reads the serial buffer and returns 1 if the message is complete(terminated by a carriage return) or 0 if not)
  char checkword(const char * string_to_compare); //compare the current word to a sting (each word is terminated by a space or the end of the message)
  char nextword(); //get the next word
  int wordtoint(); //convert the word to an integer

private:
  char *last;
  char *message;
  char messageindex;
  char serialbyte;
  char *word;
  int buffersize;
  

};

#endif

Here is SerialInMessage.cpp
Code:
#include "WProgram.h"
#include "SerialInMessage.h"
#include "HardwareSerial.h"
#include "string.h"


SerialInMessage::SerialInMessage(int SIM_buffer_size)
{

        this->buffersize = SIM_buffer_size;
      this->messageindex = 0;
      this->message = (char *)calloc(this->buffersize + 1,sizeof (char));
}

char SerialInMessage::complete()
{
   while (Serial.available() > 0) {
    
      serialbyte = Serial.read();
      
      if ( serialbyte < 128 ) { // remove non ascii characters
      
            switch (serialbyte) {
                  case 13: //carriage return
                              message[messageindex]=0;
                              messageindex=0;
                              word = strtok_r(message," ",&last);
                              if (word != NULL) return 1;
                              break;
                  case 10: //line feed
                              //do nothing
                              break;
                  default: //any other character
                              message[messageindex]=serialbyte;
                              messageindex++;
                              if (messageindex >= buffersize) messageindex = 0;
            }
      }
  }
  return 0;
}

char SerialInMessage::checkword(const char * string_to_compare)
{
      if (strcmp(word,string_to_compare) == 0) return 1 ;
    return 0;
}

char SerialInMessage::nextword()
{

    word = strtok_r(NULL," ",&last);
    if (word == NULL) return 0;
    return 1;
}

int SerialInMessage::wordtoint()
{

    return atoi(word);
}


Here is an example:
Code:
#include <SerialInMessage.h>

SerialInMessage message = SerialInMessage(32);

void setup()
{
  Serial.begin(9600);

}

void loop()
{
 
  if (message.complete()) {
    if (message.checkword("hi")) Serial.println("hello");
    if (message.checkword("bye")) Serial.println("ciao");
  }

}

Logged

Thomas Ouellet Fredericks

Pages: [1]   Go Up
Jump to: