Show Posts
Pages: 1 2 3 [4] 5
46  Forum 2005-2010 (read only) / Syntax & Programs / Installation of WString library on: November 06, 2009, 03:59:57 pm
Hello, this is probably a really boneheaded question but I can't seem to get the WString library to work.

Following the instructions on:

http://www.arduino.cc/en/Tutorial/TextString

I donwloaded the zip file String.zip and ran immediately into trouble. The instructions say:

"To use, unzip it and copy the resulting folder, called String, into the lib/targets/libraries directory of your arduino application folder."

Well, my arduino application folder has no "targets" directory in it. (Version 0017 for Linux). Still, no probs, I fearlessly went and created a "targets" and a "libraries" inside it. I then dumped the contents of the String.zip file in there (the folder called "String").

I then went and killed and restarted my IDE, went to File -> Examples to find the new examples, no joy.

OK, no sweat. I went into arduino/lib/targets/libraries/String/examples/StringAppendCharacter, opened the example and copy pasted it into the IDE. Trying to compile it informed me that:

66: error: WString.h: No such file or directory In function 'void setup()':
 In function 'void loop()':

Sooo, I repeatedly tried restarting my IDE, I zapped my X server for the hell of it, nothing. The IDE stubbornly refuses to acknowledge the library. Any ideas what I 'm doing wrong?
47  Forum 2005-2010 (read only) / Syntax & Programs / Re: Multidimensional array initialisation on: November 04, 2009, 01:38:01 pm
Sneaky idea  smiley-wink thank you.
48  Forum 2005-2010 (read only) / Syntax & Programs / Multidimensional array initialisation on: November 04, 2009, 10:28:48 am
Hello forum, a simple syntax question.

I have a two dimensional array which I can both declare and initialise simultaneously like so:

int joystick1[2][3] = {{0, 1023, 0},
                                  {0, 1023, 0}};
          // this works

I 'd like to separate this into two separate statements, like:

int joystick1[2][3];   // this works

and something like:

joystick1<lots of different expressions here> = {{0, 1023, 0},
                                                                             {0, 1023, 0}};
    // Aargh!!!
which always crashes and burns with:

"error: expected constructor, destructor, or type conversion before '=' token"

So, does anyone know if I can initialise an already declared array using the {blah, blah, blah...} syntax as opposed to having to fill it in by hand, element by element?
49  Forum 2005-2010 (read only) / Development / Re: Hacking the SDuFAT lib on: September 15, 2010, 01:50:38 pm
Well, the Libelium Sd module with the butchered lib will most probably do nicely for my current project. For my future projects however, I think this shield from Adafruit looks very promising:

http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=243
50  Forum 2005-2010 (read only) / Development / Re: Hacking the SDuFAT lib on: September 15, 2010, 11:26:33 am
Hmmm, had a look at the sdfatlib but they are using Adafruit's GPS shield. I am using Libelium's microSD module for Arduino. I was hoping one of the two ways the module slots into the Arduino would work (most likely the SPI) but no such luck, I 'm getting a "card.init failed" when trying to run the example sketches. It looks like Libelium's shield is not happy with the sdfatlib as mentioned here:

http://code.google.com/p/sdfatlib/issues/detail?id=1

Unfortunately, Libelium's microSD module seems to be the only minimalist solution for SD cards, as far as the playground is concerned:

http://www.arduino.cc/playground/Learning/SDMMC

all other pieces of hardware are shields for something else which also happen to have an SD reader.
51  Forum 2005-2010 (read only) / Development / Re: Hacking the SDuFAT lib on: September 15, 2010, 01:53:56 am
Thanks davekw7x, I will have a look, it's just that I had started mucking around with SDuFAT (all I had at a place with no net connection so was stuck with it) and wanted to see it through.

mowcius, (and anyone else who is interested), just PM me your email and I 'll send you the files.
52  Forum 2005-2010 (read only) / Development / Re: Hacking the SDuFAT lib on: September 14, 2010, 05:09:14 pm
Um, how do I add to the playground? I tried registering through the Login form:

http://www.arduino.cc/playground/Main/LoginForm

and my forum username got automatically filled. I pressed register and got some positively sounding screen (don't remember what it said) and that was that. Doing it again, gets me a "Sorry, that Username is already taken. Please press Back and try again..." which indicates I must have registered.

However, looking at:

http://www.arduino.cc/playground/Main/Participate

I read that "Unfortunately for the moment we are unable to use your same username and password from the Arduino Forum".

So, what happened? Should I try registering again with another username? But then, why did I seemingly succeed the first time round?
53  Forum 2005-2010 (read only) / Development / Re: Hacking the SDuFAT lib on: September 14, 2010, 04:16:05 pm
Hello again. I have butchered the lib and it now seems to behave OK for the job I need it to do. I 'm writing 35 byte sentences at an average of 124 ms without any obvious errors.

However, I can't figure out how to attach a file (zip of the .cpp .h and example sketch). Copy pasting the whole thing seems like a daft thing to do. What should I do?
54  Forum 2005-2010 (read only) / Development / Hacking the SDuFAT lib on: September 12, 2010, 02:22:38 pm
Hello, please bear with a rather long post from someone who doesn't really know C++.

I have a simple project, reading some sensors (3 ADC readings) and logging the results. The readings are not too close to each other, once every about 10 seconds or more is fine.

For the logging part, I have tried to use an SD card and the SDuFAT library.

The problem is, the lib has many limitations. One of the most obvious ones is that you can't create files so you have to have a preexisting file. This is not too big a problem, the card I 'm using is about 1.9GB so I just create a 1.8GB file called “data.txt” in it.

A few minor bugs are easy to fix, for example:

1- the lib tries to append to preexisting file “hola.txt”. See SDuFAT.cpp, function “int SDuFAT::append(const char* filename)”, line 454:

return print("hola.txt", data);

This is fixable by changing it to:

return print(filename, data);


2-  The lib knows where the file ends when it hits EOF, in this case 0x03. The problem is it gets overenthusiastic when deleting as it tries to write an EOF at the start of EVERY block. Try that with a file of a couple of GB and you could be waiting a century or two.

Fortunately, this is also easy to fix, in  SDuFAT.cpp, function "int SDuFAT::del(const char* filename)", line 173, I have changed line:

for(long m = 0; m <= sectors; m++) {

to:

for(long m = 0; m <= 1; m++) {            // or change 1 to whatever block you want to stop at

which makes it write to the first couple of blocks. The example sketch seems to be running fine so far and function "int SDuFAT::cat(const char* filename)" seems not to have trouble identifying the end of file without needing to fill up the start of a few trillion blocks with EOFs.


This, however, is all the low hanging fruit I could find. The real trouble begins now and its name is "int SDuFAT::print(..." family of functions.

I found out by trying to write lines of about this size:

dd/mm/yyyy,hh:mm:ss,AAAA,BBBB,CCCC

roughly 35 chars including the newline. The first few lines take just over a second to write. However, this time increases and eventually cripples the application (in my case, where logging occurs once every ten seconds, the moment writing takes longer than that I 'm out of the game).

To find out what's happening I had a look inside "SDuFAT.cpp", function "int SDuFAT::print(const char* filename, char* data)", line 353, which is what all the other "SDuFAT.print..." redirect to.

A rather major problem is that SDuFAT does not keep an internal variable as a file pointer in order to know where we are in the file. Thus, every time a "print" is used, the lib has to go over the whole file to see how big it is (statement "long file1Length = usedBytes(filename);", line 360).

This is OK for short files but as the file gets longer and longer (and given that the SD card is a damn slow beast) it becomes increasingly slow until the whole thing becomes unusable.

To make matters worse, function "int SDuFAT::println(const char* filename, char* data)", which is what most logging applications would use if the calling function does not bother adding the newline to the passed string, calls "int SDuFAT::print(const char* filename, char* data)" twice, once with the string and once with the newline. This means we read the whole damn file twice to find where we are supposed to be writing.

I tried a quick and dirty fix, passing a string with a newline appended to "int SDuFAT::print(const char* filename, char* data)" from inside "int SDuFAT::println(const char* filename, char* data)". Here is my version:

Quote
int SDuFAT::println(const char* filename, char* data)
{
  // Hackdition 11/9/2010
  // "data" is presumably terminated by 0 so find the last char, dump a \n in its place and shift it one down
  int datalength;
  for (datalength=0; data[datalength] != 0; datalength++ );   // find the position of the 0 in the passed array
  char dataln[datalength + 2];                                // make a new array one larger than the passed one
  for (int i=0; i<datalength; dataln = data[i++]);       // copy the original array into the new one
  dataln[datalength] = '\n';                                // put a '\n' at the penultimate position of the new array
  dataln[datalength+1] = 0;                                     // put a 0 at the end of the new array
  int aux = print(filename, dataln);                          // send the new array to the SD card
  // End of hackdition 11/9/2010
  return aux;
}



This should work and indeed does, until you try passing a big string to it at which point hideous things happen. The board hangs, or keeps resetting. Initially I though it was happening when the string was longer than 512 bytes but I soon found out that it happens for shorter strings too. I eventually realised that duplicating the passed string "data" by copying it to locally created "dataln" was making the board run out of memory and all hell was breaking loose. However, I didn't want to throw in the "String" lib to concatenate "data" with a newline as it would make the whole thing heavier still. An inelegant solution is to delete the "println" functions from SDuFAT.cpp and simply pass a newline-terminated string from the calling function to begin with. Any other ideas would be welcome but don't worry too much about it, it's a minor problem.


Now, to the real gritty stuff, the guts of "int SDuFAT::print(const char* filename, char* data)", the workhorse of the "print" family. As far as I can understand, it does weird things, some of which I 've already talked about but let's have another go.

First, it figures out where to write in the most hideous way possible, by reading the file (line 360).

It gets the passed string "data" and copies a chunk of it (up to BYTESPERSECTOR) to class variable "buffer"(line 378) .  It then fills up the rest of the buffer with EOF (line 385). It then goes and writes the buffer ten times (WTF!) to the card (line 390) at the  position it has calculated initially.

If the passed string overflows  BYTESPERSECTOR, it goes and copies the rest of it into "buffer" (line 404), dumps an EOF after it (line 411), fills up with blank spaces (line 416, why not EOFs like before?) and again writes it ten times to the card (line 421).



So, the obvious questions of a relative noob like myself are. Why are things written ten times? Robustness against failings of the hardware? If so, is it OK to add something like:

#define NUMBER_OF_WRITES 10      // or whatever >=1 you feel lucky with, punk

to "SDuFAT.h" and allow people to try their luck with their hardware if they are willing to risk it for greater speed?


And the most important question, should I try to add a class variable, say "long position_in_file" which gets incremented by, say, "count" after line 390 and "count2" after line 421? Then, instead of calling "usedBytes()" and reading through the whole file every time "int SDuFAT::print(const char* filename, char* data)" is called, it could simply look it up and save a hell of a lot of time. Am I missing something obvious?
55  Forum 2005-2010 (read only) / Development / Re: Wire library and blocking read/writes on: May 31, 2010, 03:46:46 am
OK, much clearer now, thanks a lot for your help.
56  Forum 2005-2010 (read only) / Development / Re: Wire library and blocking read/writes on: May 30, 2010, 02:35:07 pm
No no, I 'm just curious. I came across the hanging issue while mucking about and thought it was to do with the library which is why I started the thread. Then, after the replies, I started playing with the different boards and got the results I describe above. I don't have a problem as such, just exploring how the Wire lib works and how robust it is. I 'm still wondering why my recent Duemilanove sketch does not require external pull ups like my older ones did (and why it doesn't work with external pull ups when they shouldn't make a difference), why the ranger hangs the Duemilanove but not the Mega etc. Sure, I 'm a bit uneasy about a bus which can hang the board (a flying robot for example would be really unhappy if part of a sensor cable came undone and the whole thing froze) but I have no problem at the moment. Thanks for the help, if it wasn't for you guys I 'd still be trying to figure out the library code.
57  Forum 2005-2010 (read only) / Development / Re: Wire library and blocking read/writes on: May 30, 2010, 10:28:26 am
Guys, thanks for taking the time to help, I 'm as mystified as you are about what's happening. Let me tell you my newest discoveries and you can let me know what you think.

I let go of the Mega for the time being and went back to a Duemilanove. I wired up the compass as shown in this tutorial, uploaded the chopped up sketch I have quoted above, fired up the serial monitor and ... nothing.

I was pretty amazed since I have been using this exact same circuit with this sensor before so I double and triple checked my circuit and all seemed in order. Then I decided to pull out the pull up resistors and everything started working. The only thing that has changed as far as I can tell from my previous circuits is that I switched to the 0018 IDE. Is it possible that internal pull ups have been enabled for the Duemilanove in the new IDE?

Anyway, my Duemilanove is happily chatting to the compass using the above sketch by plugging its SDA and SCL directly into the board and its power lines directly into the board's power. Now:

a) removing either SDA or SCL does NOT hang the sketch but the returned values are all zero.
b) removing the GND line does not hang the sketch but the returned values are all zero.
c) removing the +5V line hangs the sketch.
d) removing the GND and then the +5V line hangs the sketch.
e) further removing either the SDA or SCL line restarts the sketch but all returns are zero.

I then tried exactly the same on the Mega and I got the same results, although I once got the board to hang at step e, requiring a reset.


With the compass experimentation out of the way, I moved to a SRF08 ultrasonic ranger which also uses I2C. The Robot-electronics site has a connection diagram using the external pull-ups here. Again, I didn't use the external pull-ups (or the LCD they show) but I stole their example sketch and chopped it up, removing the LCD output and adding a timeout in their getRange() function to avoid getting trapped in an infinite loop in the sketch itself (see comments marked EDIT!!!). The modified sketch is as follows:

Quote
#include <Wire.h>

#define srfAddress 0x70                           // Address of the SRF08
#define cmdByte 0x00                              // Command byte
#define rangeByte 0x02                            // Byte for start of ranging data

byte highByte = 0x00;                             // Stores high byte from ranging
byte lowByte = 0x00;                              // Stored low byte from ranging

void setup(){
  
  Serial.begin(9600);                             // Begins serial port for LCD_03
  Wire.begin();                              
  delay(100);                                     // Waits to make sure everything is powered up before sending or receiving data
    
}

void loop(){
  
  int rangeData = getRange();                     // Calls a function to get range
  Serial.print("Range = ");
  Serial.println(rangeData, DEC);                 // Print rangeData
  
 delay(100);                                      // Wait before looping
}


int getRange(){                                   // This function gets a ranging from the SRF08
  
  int timeout = 100;                              // EDIT!!! introduce a 1/10th of a second timeout
  long lastTimeCheck;                             // EDIT!!! keep track of time in this var
  
  int range = 0;
  
  Wire.beginTransmission(srfAddress);             // Start communticating with SRF08
  Wire.send(cmdByte);                             // Send Command Byte
  Wire.send(0x51);                                // Send 0x51 to start a ranging
  Wire.endTransmission();
  
  delay(100);                                     // Wait for ranging to be complete
  
  Wire.beginTransmission(srfAddress);             // start communicating with SRFmodule
  Wire.send(rangeByte);                           // Call the register for start of ranging data
  Wire.endTransmission();
  
  Wire.requestFrom(srfAddress, 2);                // Request 2 bytes from SRF module
  lastTimeCheck = millis();                       // EDIT!!! log the current time
  while(Wire.available() < 2) {                   // Wait for data to arrive
    if (millis() - lastTimeCheck > timeout) {     // EDIT!!! make sure we don't stay in here longer than the timeout
      return -1;                                  // EDIT!!! return an illegal value
    }
  }
  highByte = Wire.receive();                      // Get high byte
  lowByte = Wire.receive();                       // Get low byte

  range = (highByte << smiley-cool + lowByte;              // Put them together
  
  return(range);                                  // Returns Range
}


Poking around in a slightly more systematic way I found that the sketch hangs under these conditions:

a) BOTH SDA and SCL lines connected, +5V line disconnected (GND irrelevant, can be either connected or disconnected).

b) EITHER SDA or SCL line connected, GND connected.

In other words, if I plug either SDa or SCL and then plug either the other or GND, the board hangs.

Moving to the Mega, things get weirder. No matter what I pull out, I can't make it hang.


So, summing up, I have tried two different simple sketches, testing a CMPS03 magnetic compass and a SRF08 ultrasonic ranger on a Duemilanove and a Mega. Under certain conditions described above, I got the Duemilanove to hang using both the CMPS03 and the SRF08. I only got the Mega to hang with the CMPS03 but not with the SRF08.

I would appreciate it if anyone with an I2C device and a bit of time to spare could try to replicate this. Thanks.
58  Forum 2005-2010 (read only) / Development / Re: Wire library and blocking read/writes on: May 28, 2010, 04:49:43 pm
Some more info, I chopped up the example sketch of the CMPS03 lib to make the
following sketch which runs without need for the lib.

Quote
#include "Wire.h"


byte deviceId = 0x60;


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

void loop()
{
 
Serial.println("About to begin transmission");
 
Wire.beginTransmission(deviceId);
 
Serial.println("About to send a 2");
  Wire.send(2);
 
Serial.println("About to end transmission");
  Wire.endTransmission();
 
Serial.println("Transmission ended");
  delay(1);
 
Serial.println("About to request data");
  Wire.requestFrom(deviceId,
(uint8_t) 2);
  unsigned int value =
((unsigned int)
Wire.receive()) << 8;
  value = value + ((unsigned int)
Wire.receive());
 
Serial.print("Data received, value is: ");
  Serial.println(value);
  
  delay(1000);
}


If you have an I2C device you want to test it with, put the relevant deviceId.

Now, the code hangs if I cut power to the compass after having printed:

"About to end transmission"

so we know that something naughty is happening at:

Wire.endTransmission();


Looking inside the Wire.cpp we find:

Quote
uint8_t
TwoWire::endTransmission(void)
{
  // transmit buffer (blocking)
  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
  // reset tx buffer iterator vars
  txBufferIndex = 0;
  txBufferLength = 0;
  // indicate that we are done transmitting
  transmitting = 0;
  return ret;
}


Now, it seems that twi_writeTo() is the guilty party so if I go to "twi.c"
("utility" folder of "Wire" library) and stick a "return 0" at the very start of
the function, my original code gets past the previous snag, only to get stuck
at:

"About to request data"

Same detective work uncovers that "Wire.requestFrom()" in "Wire.cpp" goes and
calls "twi_readFrom()" in "twi.c". Again going and sticking a "return 0" at the
start of "twi_readFrom()" unsnags my code and everything flows perfectly. Of
course all results are zeros but hey, the code does not hang.

The really weird bit is the placing of the "return" statements. When looking
at, say, "twi_readFrom()" I saw two while loops (line 129 and 153) where things
could be getting stuck and thought it would be easy to modify them to exit
after a timeout had elapsed. No such luck. The first while loop and following
code is as follows:

Quote
 // wait until twi is ready, become master receiver
  while(TWI_READY != twi_state){
    continue;
  }
  twi_state = TWI_MRX;
  // reset error state (0xFF.. no error occured)
  twi_error = 0xFF;


sticking the return immediately after the loop closing bracket still makes the
code flow without hanging so there is nothing bad happening in there.

However, placing the "return 0" after the "twi_state = TWI_MRX;"

breaks the code completely, so completely that it hangs after "About to request
data" irrespective of whether the compass is on or off.



So, any ideas what could be happening here? BTW, a couple more clues. BenF
pointed out something about the lines being pulled low and adding a
"Wire.available()" before trying to read. Now, the (first) hanging occurs after
"Wire.endTransmission()" so that is not really an option. However, notice that
I 'm using an Arduino Mega and not a Duemilanove. Now, from what I remember in
the Duemilanove you have to use a couple of pull up resistors to pull the SDA
and SCL lines to +5V. In the Mega pulling the lines up results in nothing being
read so I plug
the lines directly to the relevant pins (20 and 21). Could that be significant
i.e., the internal wiring of the Mega not be the same as that of the Duemilanove
where the pulling up was done externally? After all, if the lines were pulled up
internally, nothing would change if I also pulled them up externally, right?

One more clue, when I cut power to the compass (without having altered the libs)
and it hangs after printing:

"About to end transmission"

when I restore power, the value read is zero, as opposed to the expected value.
This leads me to believe that something somewhere really does time out but then
the result does not trickle up to my sketch.
59  Forum 2005-2010 (read only) / Development / Re: Wire library and blocking read/writes on: May 28, 2010, 04:38:43 am
Are you guys sure? I am using the CMPS03 library which adds the following sketch to examples:

Quote
#include "Wire.h"
#include "CMPS03.h"

CMPS03 cmps03;

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

void loop()
{
  Serial.println(cmps03.read());
  delay(1000);
}


The code hangs if I cut power to the compass and resumes when I restore it.

The CMPS03 lib is very simple, here is the read() function.

Quote
unsigned int CMPS03::read ()
{
      Wire.beginTransmission(deviceId);
      Wire.send(2);
      Wire.endTransmission();
      delay(1);
      Wire.requestFrom(deviceId, (uint8_t) 2);
      unsigned int value = ((unsigned int) Wire.receive()) << 8;
      value = value + ((unsigned int) Wire.receive());
      return value;
}


I 'm fairly certain the guilty party is twi.c or perhaps Wire.cpp. I have managed to remove hanging by sticking "return" statements in various places such as twi_readFrom(), twi_writeTo() or TwoWire::endTransmission() for example, this removes the hanging by always returning 0 so it's useless but it points to these libs as being the hangers. I 'm using the 0018 IDE on a kubuntu 64-bit Linux platform.
60  Forum 2005-2010 (read only) / Development / Wire library and blocking read/writes on: May 27, 2010, 09:09:16 pm
Hello, is there any way to preform non blocking read/writes over TWI? I spend a long time staring at twi.c, hoping to stick some:

if (a long time has passed) {
  return -1 or something equally absurd;
}

flavoured statements somewhere but drew a blank.

I 'm guessing the code is expecting to respond to some interrupts from somewhere. I 'm somewhat amazed that Google doesn't seem to find much in response to this (am I missing something?), it seems to me that having the Arduino hang if a cable to an I2C device gets unplugged can be a rather serious problem for a lot of applications.
Pages: 1 2 3 [4] 5