Show Posts
Pages: [1] 2 3 ... 35
1  Using Arduino / Project Guidance / Re: 3 XBees Communication on: July 20, 2014, 11:59:50 pm
I just got your PM to join this thread.

I'm not that familiar with more than 2 XBEEs communicating. But once you get into a network type mode I doubt you can have T1 and T2 transmitting willy-nilly and expect R3 to understand who is saying what when, not to mention data collisions when T1 and T2 just happen to try to transmit simultaneously.

You may need to define a protocol where T1 and T2 don't transmit anything unless asked. Then have R3 poll each individually. Either strictly alternating, or if one bit of data needs to be updated more often than the other by some pattern to match the data requirements. You may need to set up some sort of mesh-like network, but I'm not sure.

Anyone else more experienced with multi-XBee networks?

BTW, why are you using PuTTy to configure the XBees. Because you are using PuTTy, that tells me that you are on some Windows variant. Digi has a tool called XCTU that runs on Windows that provides a GUI for configuring XBee modules. Much easier to use than remembering what all the AT codes mean.

I'm about to head to bed so I don't have the time to look anything up for you right now. I'll try to get to this after work tomorrow. Hopefully I won't forget. ;-)
2  Using Arduino / Programming Questions / Re: Serial.print() issue or maybe something else on: July 08, 2014, 02:35:05 pm
I notice in your code Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);... Which Arduino are you using? You never mentioned.

Also,
Quote
One weird symptom I noticed is that whenever the program reaches the GSM method client.connect() the arduino IDE loses serial connectivity. The arduino still shows up in device manager but the IDE just says COMPORT not found. Also client.connect() seems to successfully connect to the server but still returns false in the program. It just tries to connect again and again even though it is succeeding.

This almost sounds like the GSM module is trying to pull too much current, pulling down your voltage source causing a brownout. How do you have everything powered?
3  Using Arduino / Programming Questions / Re: Must have more files! (Datalogging to SD card) on: June 27, 2014, 08:00:47 am
, I need it to make a new file for every series of data. So it will turn on, record the data to a .txt file and then be turned of when the test is over. Then when it is booted back up again it needs to make a new file.

Surely, you already use an RTC. This will give you a new file by datestamp. It surely can't get any simpler than this. I just use it daily but you can move or expand to H:M:S as you need.

Silly me, I didn't take note that bhay (OP) was already using an RTC. Another way of using the RTC to generate file names that are chronologically sequential is using either secondstime() or unixtime(). From RTClib.h:
Code:
    // 32-bit times as seconds since 1/1/2000
    long secondstime() const;
    // 32-bit times as seconds since 1/1/1970
    uint32_t unixtime(void) const;
(Hmmm... there seems to be a potential glitch with secondstime() being a signed value...)

A 32bit value represented in HEX will fit an 8 character filename, but isn't quite human readable so I'd also put a human readable date/time stamp at the beginning of each record/line of the file. But it should alphabetically sort properly.

Just change the sprintf(filename, "%02d%02d%02d.csv", now.year(), now.month(), now.day()); line in your sample code to sprintf(filename, "%08x.csv", now.unixtime()); or sprintf(filename, "%08x.csv", now.secondstime());

Though, I suppose (since the SD library supports sub directories) one could use folders with dates as names with files with times as names to have it human readable at the filesystem level.

The scheme to create numbered files will work,  but it might take a long time to check for all the numbered files which already exist.

What I did was created a file with the lastest file number in it.   The program opens this file,  reads the next number,  increments it in the file, and then closes the file,   and opens the actual data file with the number.

Clever solution. Though I'm not really sure how long the code would take to realize that ...99.CSV is the next available file. And I don't have any of my Arduinos handy to empirically find out.

I've found a big problem with sd files becoming corrupted.  I'd endorse the suggestion to have a switch which disables file writing before powering the device off.

One trick that I've developed for at least the prototype stage on my UNOs: If available use two adjacent I/O pins. Configure one pin as an output at LOW, and the other pin as INPUT_PULLUP. I have a 2-pin section of pinheader that I've soldered a wire across the short ends that I use as a male shorting block. No, I wouldn't suggest using this technique as an input switch (bounce would be horrible I imagine), but as a rarely-changed jumper setting it is sufficient and doesn't require any wires to a breadboard.
4  Using Arduino / Programming Questions / Re: Must have more files! (Datalogging to SD card) on: June 26, 2014, 09:21:40 pm
You're using the number of existing files to choose a name for the new file. It might work, but only when all the previous files are present. If you ever deleted one of the historical files, while leaving the most file in place, this algorithm would leave you trying to use the name of an existing file, so it would fail.

The approach Sembazuru demonstrated is closer to what I was trying to describe.

Well, with my technique (especially since the Arduino doesn't naturally have an RTC for date stamping files), if one deletes a file from the middle of multiple files, then my technique will fill in the empty spots, essentially destroying any sort of link of chronological order to sequential order. I just needed something quick and dirty when I wrote that.
5  Using Arduino / Programming Questions / Re: Must have more files! (Datalogging to SD card) on: June 26, 2014, 03:57:02 pm
Here is how I did something similar a while ago. This technique will give you up to 100 incrementally numbered files (00 through 99).

Code:

#include <SPI.h>
#include <SD.h>

char fileName[] = "LOGGER00.CSV";  // Base filename for logging.

void setup()
{
  // Construct the filename to be the next incrementally indexed filename in the set [00-99].
  for (byte i = 1; i <= 99; i++)
  {
    // check before modifying target filename.
    if (SD.exists(fileName))
    {
      // the filename exists so increment the 2 digit filename index.
      fileName[6] = i/10 + '0';
      fileName[7] = i%10 + '0';
    } else {
      break;  // the filename doesn't exist so break out of the for loop.
    }
  }
}

I would suggest that every time you need to write you should open the file and then close it immediately after writing, or open the file once and always send a file.flush() after writing. This should help reduce the chance of loosing data, files, or the SD card when you power off the Arduino. I suppose if you really wanted to be safe, have a switch that you throw that disables writing so you can be sure that the write buffers are flushed and you aren't actively accessing the SD card before you intentionally power off. But, that wouldn't cover accidental power outages.
6  Using Arduino / Programming Questions / Re: Convert amount received by the serial on: June 22, 2014, 08:44:45 am
Quote
The issues with your sketch is it makes too many assumptions about the incoming serial stream.

It works under the conditions I listed.

Quote
I'm not going to bother doing the math to see if your 2ms delay is long enough, I'll assume you've already found that to be true.

Sounds like you can't do the math, as the code works as described.  Why are you whining about simple code that demonstrates the "int n = readString.toInt();" function? Did I somehow make your cornflakes taste like urine?  smiley-cool

I'm sure it works under the conditions that you listed (i.e. each number sent as a burst of digits as fast as the serial port's baud rate would allow). And it isn't that I can't do the math, I just didn't bother because I trusted you enough not to intentionally post non-functional code. I was just pointing out the fragility of the code. Your code certainly won't work if the transmitting serial device (UECIDE Serial Terminal, any one of a number of standalone serial terminal emulators like Realterm, serially connected keyboard, etc) is sending multi-digit numbers one character at a time at the speed a normal person types. For robustness it is best to watch for an end token (like a newline character) instead of relying on a timeout.

No need to imagine urine flavored cornflakes.  smiley-razz
7  Using Arduino / Programming Questions / Re: Convert amount received by the serial on: June 21, 2014, 07:36:00 pm

There are a few issues with your suggestion zoomkat. I'm not going to argue pro or con on the String object, I expect that from you so I would be surprised not to see it. The issues with your sketch is it makes too many assumptions about the incoming serial stream. I'm not going to bother doing the math to see if your 2ms delay is long enough, I'll assume you've already found that to be true. The assumption your code is making is that each set of digits for the numbers will be sent in a burst as fast as the serial port baudrate will allow, and there will be at least a 2ms delay between numbers (bursts of digits). Also, the error condition (i.e. a non digit character starting a new burst of serial transmission) will result in getting a value of zero. What if zero is a valid number to accept? An error transmission will be giving false values (instead of either being ignored or producing an error message).

It will work in many cases, but it just isn't robust enough for all reasonable cases.
8  Using Arduino / Programming Questions / Re: Convert amount received by the serial on: June 21, 2014, 10:41:23 am
Say you read in a 5, it's currently a char type so you need to make it an integer. To do this, you take whatever char comes in(preferably a digit) and subtract 48 or '0' from it. 5 as a char is 53, then subtract 48 and you get 5.

Now this is when you use (temp = temp * 10).
Temp is currently 0, so it looks like this: 0 = (0 * 10) + ("incoming char");
You add the 5 now. 5 = (0 * 10) + 5;

Ok now read in a '9'. Subtract 48 to give you 9.
59 = (5 * 10) + 9;

Add another char 8, subtract and now you have:
598 = (59 * 10) + 8;

If you keep reading in chars, it will keep storing them. Note an int is only so big, so if you go over 32767, you will start to get negative numbers. To fix this you can either make the variable temp "unsigned" or type long or even unsigned long.

@Gilliard
Continuing HazardsMind's logic, you probably also want to have your Arduino know when you have finished sending a number and want to start sending a new number. To do this you need to have some sort of token that you use to tell the Arduino to either start building a number from sequential digits and/or stop building a number from sequential digits.

Commonly an end token is used, either in the form of a carriage return and/or a line feed character (depending on what your system uses for an newline character or sequence when you press the return key). Using current technology, it is probably safe to just watch for the line feed character because both MS-Win systems and HTTP use the sequence carriage return then line feed, and Unix-style systems (linux, OS-X, actual unix, android, etc) use just the line feed character. Because of your check to make sure the incoming character is a digit, the carriage return character will be ignored so you can just focus on the character that is common in the two (modernly) common newline character sequences. But if you are going to be connecting to an old-school Mac running OS9 or earlier, it will use just the carriage return character (and as I recall the same thing is true about C64s)... If you can reasonably expect to connect to an old dinosaur Mac (don't laugh, the lab I just started working at has an old PC running Windows 3.1 because that is the latest OS that runs the needed software and has the proper hardware drivers for the attached expensive equipment, classic "if it works don't fix it") you may want to check for a carriage return OR a line feed.

Check this wiki page if you are interested in the history of newline character sequences.

A start token might be useful to tell the Arduino what variable the following sequence of numbers should be stored in. This is useful if you want to be able to control multiple parameters via the serial port.
9  Using Arduino / Programming Questions / Re: Installing 3rd party libraries without . on: June 21, 2014, 09:52:50 am
Hi, I'm a newbie so my apologies if this  is a stupid question but how do you install 3rd party arduino libraries when there is no .cpp and .h (or zip) file, just the code? I've done it successfully with those files before (eg for AccelServo) but the third party library links take you straight to the code in your browser. How do you get the .cpp and .h file? For example, I'd like to install Tim Herzel's Wii Classic Controller library:
http://playground.arduino.cc/Main/WiiClassicController

It's just a page of code with no links to any files to download. Do I copy it into a text document and save it as .cpp or .h?

If you look carefully on that particular page there are actually two pieces of code, each listing ending with a right-justified link called "[Get Code]". At the beginning of the code listings (in a different font) there is a description of what the following code listing is for.

For pages like this (and there are a lot in the playground), it is probably best to click the [Get Code] link at the end of the listing(s) and then save the resulting page as the proper name either alluded to or directly stated in the text before the beginning of the listing(s). It is then up to you to move the resulting files from your downloads area into the proper folder structure.

There will always be a .h file, but as you can see in the example you linked to, sometimes the .cpp file isn't needed.

That said, some of the pages in the playground are woefully out of date. One example that I know of is the RunningMedian  library. I worked with robtillaart adding some functionality to that class, but he never got around to back-porting the changes to the Playground Page. One would just have to know to search for him on github to find the latest version of that library.
10  Using Arduino / Programming Questions / Re: Updating sketch from old IDE serial HELP!! on: June 20, 2014, 01:44:54 pm
i don't understand what you mean. do you want me to try my code outside of the interrupt and in the main loop ?

Wait... You are trying to write to the hardware serial port from within an ISR? As of Arduino1.0+ the serial access is now asynchronous, meaning it uses interrupt events. Not something you can do from within an ISR. Best to set a flag inside the interrupt and then have your main loop continuously poll the flag. Then print and clear the flag if the main program finds the flag set.
11  Using Arduino / Programming Questions / Re: Read variables from SD Card on: June 12, 2014, 07:48:57 pm
I am a bit confused on how I do add error checking capabilities, or for example, keep a backup should the file become corrupted?

No need for a backup for what I was talking about. What I was envisioning is because you (should) know what the data you are reading from the file should look like (because you wrote the code that actually did write it). If what you actually read from the file doesn't match the formatting of what you expect, presume there is an issue and either look for a previous record or just use a default value.

I see. I am using something similar reading from the serial port. It checks if the data is a numeric constant, if not it discards and waits for the next result. I guess I could use something similar here.

I am just wondering what would happen if the actual log file got corrupted, for example a power down in the midle of a reading?

Honestly there is only so much you can plan for. There is always the slight possibility that if power was interrupted during a write to the SD card you could actually corrupt the SD card itself. The power would have to be lost at just the right (or wrong?) time. Best case would be a partial record saved.

Depending on how critical not loosing data is, you might want to consider a backup battery for the Arduino. Sense the main input power to the Arduino (I haven't thought through far enough to flesh out an actual circuit yet), and when the main power dies, prepare for a clean power off (make sure any records that need to be written are completely written) and then switch off the power from the backup. I personally think that this is overkill, but you may have different priorities.
12  Using Arduino / Programming Questions / Re: Read variables from SD Card on: June 12, 2014, 07:13:09 am
I am a bit confused on how I do add error checking capabilities, or for example, keep a backup should the file become corrupted?

No need for a backup for what I was talking about. What I was envisioning is because you (should) know what the data you are reading from the file should look like (because you wrote the code that actually did write it). If what you actually read from the file doesn't match the formatting of what you expect, presume there is an issue and either look for a previous record or just use a default value.
13  Using Arduino / Programming Questions / Re: Read variables from SD Card on: June 12, 2014, 04:43:10 am
This would be a bit easier if we knew exactly how you are saving records to the SD card to know how to parse the file. So, without that knowledge, I'll just have to speak on general terms.

Since you are writing to a SD card I'll assume you already know the reference page for the SD Library. Let me highlight some functions that you will want to read up on: file.size(), file.seek(pos), and file.peek().

When you open a file object one of it's properties is a read/write pointer (or can be called a cursor). Some programming languages use two pointers, a read pointer and a write pointer. With the SD library we only have one pointer that does both jobs (I'm not totally clear if the reason is because of how the SD library was written, or if that is how C/C++ deals with file classes, but that level of detail really doesn't matter.) So one needs to remember to move the pointer to the end of the file before writing to avoid overwriting parts of the file.

When the last time your Arduino was on and writing to the data file it may have recorded lots of records. One should expect to find 0 to [very large number] of records. Think of the records as pages in a book. If you just want to know what is on the last page of the book do you start reading from the beginning, or do you turn to the last page? Reading the whole thing might be feasible if the "book" was a short 4-page menu, but what if it is the Oxford English Dictionary? Would you really read through all 12 volumes (for OED1) just to look at the last page? Unfortunately, there the analogy starts to break apart. One can't simply turn to the last saved record in the file. But one can turn to the last byte in the file using file.seek(pos). One knows where that last byte is by using file.size(), and one can see what that last byte is without moving the read/write pointer by using file.peek(). Then it is a simple exercise of scanning backwards from the end of the file looking for your record separator (if you used file.println() when writing to the file your separator would be <CR><LF>, but since you can only scan one byte at a time, just scan for the <LF> character.) Then read and parse the end of the file much like one would read and parse the same data coming in over the serial port (except instead of using Serial.read() you would use file.read()).

Hmmm... I suppose one could modify the analogy to fit the exercise better... Think about what you would do if you wanted to read the last chapter of Harry Potter and the Order of the Phoenix? Do you start flipping through pages from the front of the book, or start flipping pages backwards from the last page (page 870 of the US printing)? (I'm ignoring the possibility of a table of contents...)

Remember to put error corrections in there. Like consider what to do if the file isn't found, if the SD card isn't found, what to do if the last record isn't complete or is corrupted, etc.

My suggestion would be to write it as a function that you only call from setup(). That would keep the clutter down in setup(), and allow using local variables in the function that will cease to exist (and thus stop consuming valuable RAM) once the function completes. The 4 bytes of the unsigned long that you will be using to keep tabs of and manipulate the read/write counter should be a local variable, I'm sure there will be others...

Hopefully this is enough for you to cobble together some code that you can then post for us to critique. Not all of us are very tolerant of massive amounts of hand-waving. smiley-wink
14  Using Arduino / Programming Questions / Re: Using Random() on: June 05, 2014, 03:50:48 pm
but

Code:
randNumber = random(1,5); // generate random number between 1 & 4 (minimum is inclusive, maximum is exclusive)
  if (randNumber >= prevRand) randNumber++; // corrects for values equal to the previous value,
              //and shifts values greater than previous values up by one to get a generated range
              // of 1 to 5 excluding the last generated value
  prevRand = randNumber;

if the prevRand is 4 and randNumber too, randNumber will be 5 and therefor out of range !!!

Except that the stated range from the OP is 1 through 5 inclusive.

Quote
you should correct for that.  
Furthermore this method will generate "predictable" pairs  e.g. after a 1 there are twice as many 2's as statistically expected.

There is a reason why it's called pseudorandom...

Quote
This code will never generate the same random number. If there is a "collision" with the previous value an offset is added. Then the offset is changed so that no predictable pairs come up (unless the range is only 2  as in example below) .  As the code has no loops it has a predictable execution time [range].
Code:
int prevValue = -1;
int x = 0;
int y = 0;
long count = 0;
 
void setup()
{
  Serial.begin(115200);
  Serial.println("Start ");
}

void loop()
{
  x = getRandomNoDuplicate(1, 3);  //  gives "random" 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 (very predicatable!!
  if (x == y) Serial.println("...");
  y = x;
  count++;
  if (count % 1000 == 0) Serial.println("M");
}

int getRandomNoDuplicate(int lower, int upper)
{
  static int offset = 0;
  int randNumber = random(lower, upper);
  if (prevValue == randNumber)
  {
    offset++;
    if (offset >= upper - lower) offset = 1;
    randNumber += offset;
    if (randNumber >= upper) randNumber = lower + randNumber - upper;
  }
  prevValue = randNumber;
  return randNumber;
}

Looks good to me. I'd have to take some time (which I don't have at the moment) to fully study it, but I feel that there is still a possibility of duplicates for some values of offset on some ranges due to rollover effects. I could be wrong though.
15  Using Arduino / Programming Questions / Re: Using Random() on: June 04, 2014, 03:30:59 pm

the problem with this loop

Code:
do
  {
    randNumber = random(1,6); // generate random number between 1 & 5 (minimum is inclusive, maximum is exclusive)
  } while (randNumber != prevRand);
is that it is
- undefined how long it will take (in theory a deadlock) especially if the range is small

in practice it will work

True. I suppose a slightly different approach to avoid potential multiple loops would be:
Code:
byte randNumber;
byte prevNumb = 1; // make sure this value is within the random range.

void setup()
{
  Serial.begin(9600);
  randomSeed(analogRead(0)); // Probably not the best random seed, but it is what is suggested in the Arduino reference
}

void loop()
{
  randNumber = random(1,5); // generate random number between 1 & 4 (minimum is inclusive, maximum is exclusive)
  if (randNumber >= prevRand) randNumber++; // corrects for values equal to the previous value,
              //and shifts values greater than previous values up by one to get a generated range
              // of 1 to 5 excluding the last generated value
  prevRand = randNumber;
  Serial.println(randNumber); // show the value in Serial Monitor

  delay(1000); // wait 1 second before displaying the next number
}

Again not compiled to check for syntax errors...
Pages: [1] 2 3 ... 35