Show Posts
Pages: [1] 2 3 ... 35
1  Using Arduino / Project Guidance / Re: 3 XBees Communication on: August 04, 2014, 10:48:45 pm
Because there is no synchronization between transmitters with your 2 transmitter and 1 receiver you will need to change communication paradigms to the receiver polling the transmitters for responses. For this, you might want to start referring to the transmitters as "slaves" and the receiver as "master". The slaves won't transmit anything unless asked, so it is up to the master to request data from the slaves. This is commonly known as polling.
From wikipedia's entry on Polling:
In a multidrop line arrangement (a central computer and different terminals in which the terminals share a single communication line to and from the computer), the system uses a master/slave polling arrangement whereby the central computer sends message (called polling message) to a specific terminal on the outgoing line. All terminals listen to the outgoing line, but only the terminal that is polled replies by sending any information that it has ready for transmission on the incoming line.

Basically, your master Arduino would send a message out over the XBees and both slaves will listen. If the polling message is for the temperature sensor Arduino (say the character "*"), it would respond with the temperature. May as well keep the current message format, but change the XBeeTX.print to XBeeTX.println which will add a CR and LF to the end of the message. Ignore the CR (0x0D) and use the LF (0x0A) as an end-of-message character. For the same polling message for the temperature sensor, the RPM sensor would throw out all received characters until it gets the LF, and then it would start listening for another character.

It might make sense in your setup for the temperature Arduino to only query the I2C temperature sensor when it gets polled for data. Then have the RPM Arduino to continually count Hall Sensor triggers and calculate new RPM values, and when it gets polled respond with the latest calculated value.

As far as the code you posted:
  • Yes, data_format[] as you define it will/should work. (kudos to you) :-)
  • Regarding RPM calculations, what is the range of RPM you are expecting (and thus what is the fastest and slowest that 5 rotations will be counted)? Will the maximum RPM be below the maximum value that an unsigned int can hold (65,535)?
  • More kudos to you, good on you for keeping your ISR (rpm_fun) short and sweet. I might choose a more suitable name like rpm_count, but that is mostly personal preference.
  • Something to be careful with your actual calculation (rpm = 60000/k*revolutions). You are doing integer math with longs and then storing the result into an int. Watch out for rounding errors and unintentional implicit casting truncating your values. I'm no expert on figuring these things out, so you might want to do some trials on your math in a scratch sketch. Give the largest and smallest values to the variables k and revolutions that you would expect to see, then run the formula. Check to see if the result matches what you expect. If not, you may have to do some explicit casting. Someone else may have to assist with this, my skills here aren't up to par yet. For all I know, because I haven't tested it yet outside my own mind, your formula may work properly for your situation. But I would devote some time trying to break this to understand any potential limitations.
  • When rebuilding the received message composed with "%c%04X", the second received byte when converted to a hex value will be shifted left 12 bits, the third byte shifted 8 bits and added to the second, the fourth byte shifted 4 bits and added to the previous two, and then the fifth byte shifted zero bits (i.e. not shifted at all) and added to the previous three.
  • Using an end-of-message (EOM) character will allow you to check each received character for the EOM character to trap some cases of malformed messages. If the EOM character arrives early, or doesn't arrive in the expected number of characters, the received message can be thrown out as bad.
Just some thoughts for you to ponder.
2  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. ;-)
3  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.

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?
4  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:
    // 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(),; 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.
5  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.
6  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).


#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.
7  Using Arduino / Programming Questions / Re: Convert amount received by the serial on: June 22, 2014, 08:44:45 am
The issues with your sketch is it makes too many assumptions about the incoming serial stream.

It works under the conditions I listed.

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
8  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.
9  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.

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.
10  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:

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.
11  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.
12  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.
13  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.
14  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(),, 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 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 you would use

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
15  Using Arduino / Programming Questions / Re: Using Random() on: June 05, 2014, 03:50:48 pm

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.

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...

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].
int prevValue = -1;
int x = 0;
int y = 0;
long count = 0;
void setup()
  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;
  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)
    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.
Pages: [1] 2 3 ... 35