Go Down

Topic: Malloc? Dynamic array. (Read 3677 times) previous topic - next topic

tof

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: [Select]
#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: [Select]

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

}; */

Thomas Ouellet Fredericks

tof

Here is an example:

Code: [Select]
#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");
 }

}
Thomas Ouellet Fredericks

mellis

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?

tof

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: [Select]


#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: [Select]

#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: [Select]
#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");
 }

}


Thomas Ouellet Fredericks

Go Up