SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By thegrinch
#199800
Hi, I am working on a project where I would like to read multiple TFMini sensors using an Arduino Uno. I am trying to accomplish this by using multiple software serial objects in my code like so:
Code: Select all
#include <TFMini.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
SoftwareSerial mySerial2(12, 13);
TFMini tfmini;
TFMini tfmini2;
And using SoftwareSerial.listen() to switch between the two in my main loop like so:
Code: Select all
  mySerial.listen();
  uint16_t dist = tfmini.getDistance();
  //do some LED stuff with the value
  delay(10);
  mySerial2.listen();
  uint16_t dist = tfmini2.getDistance();
  //do stuff some other LED with the other value
  delay(10);
I've notice this method works at first but both TFMini's have a tendency to get stuck in a hung state where they return the same value forever until power they're power cycled. This pretty much happens every time I run my patch within a few minutes of starting it.

What might be causing this error?

It doesn't happen when I run my patch with only one mini. It seems that doing the software serial transaction with one TFMini then with another would logically work fine, since it's just switching back and forth between two pairs of digital pins sending a message and doing a read, but perhaps there's something in the TFMini library that works differently than this. Thanks!
#199805
Those are both set like this:
Code: Select all
  mySerial.begin(TFMINI_BAUDRATE);
  tfmini.begin(&mySerial);

  mySerial2.begin(TFMINI_BAUDRATE);
  tfmini2.begin(&mySerial2);
I believe TFMINI_BAUDRATE is defined as 115200. According to the product page:
The TFMini is easy to power at only 5V and easy to talk to using a 3.3V UART at 115200 baud.
So I don't think I can change the baudrate.
#199806
Folks on another forum suggested this:
These appear to use a streaming protocol. So, when switching between the two data streams, it would be necessary for the library to re-sync with the frame header in the stream to get meaningful readings. It is possible that the library you are using is getting out of sync with the device data stream.
Can anybody confirm or deny that this is the case?
#199810
The standard Softserial is only supporting 1 input-pin. It does this by enabling an interrupt to the running program at a change of level on the input-pin, disable further interrupts and then sampling the input-pin (timing based on the baudrate) for the total of 8 bits to compile a complete byte. Then it enables the interrupts again. With softwareserial.listen() call you change that interrupt-routine to happen on a another input-pin everytime. The issue is when a second input-pin started to get input, while the first input-pin was served (to get to the total of 8 bits). When you call SoftwareSerial.listen(), it might have missed 1 (or more) of the 8 bits it is expecting... and the program is getting out of sync and provide rubish. That is also how I read the remark you included. Lowering the baudrate will reduce the chance of that happening, but reading the datasheet and library and I agree you can not change that. You could try to have ONE sensor use SoftSerial() and have the other sensor read from the hardware serial() and connect to pin 2/3 (same as USB).
regards,
Paul
#199814
So would adding a delay in between the SoftSerial.listen() call and the SoftSerial.read() call fix that?

It doesn't make sense to me that the Software serial would still be expecting bits after finishing a read function (since the read function is supposed to return the full response to the serial message, after which no more reads are necessary) or that the SoftSerial.listen() would have a lag in kicking in (since it should in theory immediately start reading the new pin following execution of the function). Is there are reason that either of these would actually be the case?

It seems more likely that some sort of constant sync is necessary with these devices and that they aren't getting that when SoftSerial is switching back and forth between pins.

I can't use that hardware serial port since USB serial is necessary for other aspects of my project.
#199815
Put simply:

Does TFMini.getDistance() trigger a serial read transaction? Or does it return a value that is continually being read by some sort of callback in the library? These would seem to be the only two options. With the former my code should work, with the latter my code will have errors, so I assume it's the latter.
#199817
@SoftwareSerial: a UART is normally handling the incoming bits to compose the byte and store the byte in an internal UART buffer. It interrupts the main processor when at least one byte is available so the main processor can read from the buffer the byte(s). With SoftwareSerial / Softserial, all what is UART is normally doing is now handled by a program that runs on the main processor. This is handy if you do not have a seperate UART, BUT makes the overal performance of the system slower and as timing if extremely critical, It can normally not handle high speeds (115K) very well.
The SoftSerial package will only read from 1 input-pin (the last instance that was set). In the case of SoftwareSerial there is an extra complication that with SofwareSerial.listen(), you can switch to another input pin, HOWEVER the provided data /bits on that pin might already be in progress and is lost OR new data/bits might arrive at the current pin and that is lost as well. A delay between the listen calls could make things worse (higher chance on loosing more data /bits on the new pin). Also read : https://learn.sparkfun.com/tutorials/se ... tion/uarts.

You could consider to have external UART connected to your system.

@getdistance(): yes.. it will read the serial connection as well

regards,
Paul