Programming XBee to transmit and receive data

The leading zero was stripped by the println(var, HEX) method. (The print(var, HEX) method would do the same). For extra data it doesn't matter, but what if the high nybble of either data_high or data_low was zero. The high nybble wouldn't be transmitted at all, breaking our data stream format. Unless we can figure out if one can suppress leading zero trimming with the print(var, HEX) method, we will have to roll our own function.

Noted. I noticed the omission of the zeros, and also that println() just sets the data in the next line.

Also, when I say XBeeRX.available() == 1 and then I say data_in = XBeeRX.read(); does this byte leave the Serial buffer and go into data_in or is it copied? I think its moved right?

To make sure I received the next byte should I put XBeeRX.available() == 2 (next byte along with already existing) or still XBeeRX.available() == 1 (new byte which came in)?

I couldn't work on this today due to other appointments. But I was thinking of trying :

if(XBeeRX.available() == 1 && readPosition == 0)
{
data_in = XBeeRX.read();
if (data_in == '*')
{
readPosition++;
}
}

if(XBeeRX.available() == 1 && readPosition == 1)      [b] // I assume the byte that went into data_in is moved and not copied.[/b]
{
data_high2 = XBeeRX.read();      [b] //higher nibble of data_high[/b]
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 2)       
{
data_high1 = XBeeRX.read();       //lower nibble of data_high
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 3)       
{
data_low2 = XBeeRX.read();       //higher nibble of data_low
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 4)       
{
data_low1 = XBeeRX.read();       //lower nibble of data_low
readPosition++;
newReading = 1;
}

if (newReading == 1)
{
...
...
}

I could have enveloped a switch statement (switching the readPosition) into an if(XBeeRX.available() == 1) loop also I guess. But would this logic work?


what is the -0.01 for? I don't remember seeing anything about this in the temperature sensor datasheet. But I may have missed it.

The '-0.01' came from the code in various blogs I searched. The resolution of the MLX90614 is 0.02 and the half of it is some offset I guessed. In any case, I never gave it much thought because the resolution is good anyway.

What version of the IDE are you using?

I downloaded it from this website this year (in January).

Serial.begin(115200);
  XBeeRX.begin(9600);

Is it a better idea to set the Serial.begin() at a higher baud than the XBee.begin() baud? What difference does it make?

int frac; // what is this variable used for? Future use? Or can it be removed?

Removed I guess.

Let me run this and see what Celsius values I get.

V_88:

The leading zero was stripped by the println(var, HEX) method. (The print(var, HEX) method would do the same). For extra data it doesn't matter, but what if the high nybble of either data_high or data_low was zero. The high nybble wouldn't be transmitted at all, breaking our data stream format. Unless we can figure out if one can suppress leading zero trimming with the print(var, HEX) method, we will have to roll our own function.

Noted. I noticed the omission of the zeros, and also that println() just sets the data in the next line.

Well, technically, println() sends both the "carriage return" and "line feed" characters after what prints, so the next thing that prints will be on a new line. (In the serial monitor the cursor is moved back to the first column and advanced down 1 row.) You will need to use print() to send the 6 character buffer that sprintf() filled... Read through the last code samples that I posted.

V_88:
Also, when I say XBeeRX.available() == 1 and then I say data_in = XBeeRX.read(); does this byte leave the Serial buffer and go into data_in or is it copied? I think its moved right?

When you say XBeeRX.available() == 1, you are asking if there is exactly 1 character in the XBeeRX's buffer (it is a FIFO buffer set up by the SoftwareSerial library). You really want to check to see if there is at least 1 character (i.e. greater than zero). But all that does is check to see if there is anything available.

When you say data_in = XBeeRX.read(); then you are copying the next available character from XBeeRX's buffer and then removing that character from the buffer. (If you wanted to read it and then leave it (bad idea in most cases) you would use data_in = XBeeRX.peek();.)

V_88:
To make sure I received the next byte should I put XBeeRX.available() == 2 (next byte along with already existing) or still XBeeRX.available() == 1 (new byte which came in)?

read() removes the byte from the buffer. The buffer has a fixed size so except for rare cases you always want to pull bytes out of the buffer so it doesn't overflow and you start loosing data.

V_88:
I couldn't work on this today due to other appointments. But I was thinking of trying :

if(XBeeRX.available() == 1 && readPosition == 0)

{
data_in = XBeeRX.read();
if (data_in == '*')
{
readPosition++;
}
}

if(XBeeRX.available() == 1 && readPosition == 1)      // I assume the byte that went into data_in is moved and not copied.
{
data_high2 = XBeeRX.read();      //higher nibble of data_high
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 2)
{
data_high1 = XBeeRX.read();      //lower nibble of data_high
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 3)
{
data_low2 = XBeeRX.read();      //higher nibble of data_low
readPosition++;
}

if(XBeeRX.available() == 1 && readPosition == 4)
{
data_low1 = XBeeRX.read();      //lower nibble of data_low
readPosition++;
newReading = 1;
}

if (newReading == 1)
{
...
...
}




I could have enveloped a switch statement (switching the readPosition) into an if(XBeeRX.available() == 1) loop also I guess. But would this logic work?

Actually the code you came up with from my pseudocode did "enveloped a switch statement (switching the readPosition) into an if(XBeeRX.available() == 1) loop"... And it works as I have shown. If it doesn't work on your equipment then there may be a need to take a look at your hardware again...

Your multiple ifs will also work as well as long as you fix your comparisons, check to make sure available() is greater than zero. Checking to see if a value (any value, really) is not zero is easy because in C++ boolean false is zero and boolean true is not-zero. So if (XBeeRX.available() != 0) will evaluate the same as just if (XBeeRX.available()). Also, in the if statement for readPosition == 4 should set readPosition back to zero instead of incrementing it....

But if for some reason you want to change the name of the serial port you are accessing (like re-using this code in another project), the code I suggested there is only 2 places (in that part of the code) where the serial port name would need to change, and you would need to change it 2 places in every if (5 in this case).

There have been discussions on these forums comparing and contrasting the merits of switch case to multiple and/or nested if statements. There are some cases where one method is preferred over the other, but for most cases it comes down just to the style that the coder likes. Switch case does seem to be a more advanced (and in some peoples opinion more refined) method, but the important thing is whether you can understand it after not looking at it for 6 months.

V_88:

what is the -0.01 for? I don't remember seeing anything about this in the temperature sensor datasheet. But I may have missed it.

The '-0.01' came from the code in various blogs I searched. The resolution of the MLX90614 is 0.02 and the half of it is some offset I guessed. In any case, I never gave it much thought because the resolution is good anyway.

Well, if in theory if the temperature sensor returns a zero because it is almost at absolute zero, your equation would return -0.01kelvin which doesn't exist in traditional physics. I'd trust the data sheet and remove the - 0.01 from your code.

V_88:

What version of the IDE are you using?

I downloaded it from this website this year (in January).

I'm just curious, but to see what version it is look in the title bar of the IDE window. :wink:

V_88:

Serial.begin(115200);

XBeeRX.begin(9600);




Is it a better idea to set the `Serial.begin()` at a higher baud than the `XBee.begin() `baud? What difference does it make?

Matching baud rates between software serial objects and hardware serial ports can be a bit magical. But for this case having a faster hardware serial for transmitting means the Arduino is spending less time sending messages out to the computer, leaving more time for other things (like the bit-banging that software serial is doing).

Again, like the switch case vs. multiple/nested if statements argument, the main contributing factor is personal style. I usually have my serial monitor at 115200 baud, and only change it if I need to. Why waste time sending characters if you don't need to?

V_88:

int frac; // what is this variable used for? Future use? Or can it be removed?

Removed I guess.

Let me run this and see what Celsius values I get.

Good luck. If you have issues, try swapping the RX and TX to the XBees (either by swapping the jumpers or by swapping 2 and 3 in the code at SoftwareSerial XBeeTX(2, 3); // RX, TX) on both the Transmit and Receive Arduinos. (I don't expect you to have problems because the SoftwareSerial library example did work.)

It worked. I also removed the -0.01 from the code (not that it makes a big difference, but your logic of a negative Kelvin reading being absurd makes sense).

I have to use another sensor (a flow meter. I am thinking POW110D3B) put it in the same circuitry. So the data would then have this temperature data, along with the flow rate data which has to be transmitted wireless and broken down in the receiver end. I hope it won't be too much trouble, in any case that it is, I know I can take guidance from you XD

Thanks for all the help, I really appreciate it.

V_88:
It worked. I also removed the -0.01 from the code (not that it makes a big difference, but your logic of a negative Kelvin reading being absurd makes sense).

Yeah, not that your temperature sensor actually able to read absolute zero isn't a little absurd in the first place... XD But I'm glad you got my point.

V_88:
I have to use another sensor (a flow meter. I am thinking POW110D3B) put it in the same circuitry. So the data would then have this temperature data, along with the flow rate data which has to be transmitted wireless and broken down in the receiver end. I hope it won't be too much trouble, in any case that it is, I know I can take guidance from you XD

Thanks for all the help, I really appreciate it.

No problem. I'm glad I could help. (Don't forget to show your appreciation with the karma button.) 8)

Hmmm... temperature sensor, now liquid flow meter... Just out of curiosity, what is the full project? An aquarium monitor? Hot water meter? Thermally triggered water cannon?

A few things to think about as you approach expanding your project:

Looking at that sensor, one would need to use a tachometer type code. (Yes, that is a not-so-subtle hint at a search term to find example code.) The flow range of that sensor is 1-30 L/Min. Near the slow range, at 2 L/Min the sensor pulse is only 16Hz (or 62.5ms/cycle). Depending on your expected liquid flow you would need to decide how measure the pulses:
A) Count the number of pulses in a set time period
B) Time how long a set number of pulses takes (probably more accurate than A)
C) Time how long individual pulses take multiple times, throw out outliers and average
Transmit the count or timing information the same way (and I would probably just add it to your existing dataStream) you transmit the raw data from your temperature sensor, and calculate the actual flow rate on your receiver. (You may want to change some variable names, like data_high might want to be temp_high so you can then have a flow_high.)

No matter how you do the tachometer code, you will probably have to use an external interrupt. That means moving software serial off of pin 2 and/or 3 of your UNO on at least the transmitter. I'm sure you can figure out how to do that now. 8) You don't have to configure both Arduinos to use the same pins for software serial.

You should eventually (but probably now) change your transmitter code to not use the delay, rather use the techniques in the BlinkWithoutDelay (BWoD) example to capture a time and then perform an action after a set amount of time has passed. Look for it in the IDE Examples/02.Digital menu. The technique is sort of like cooking. You put the roast into the oven and take note of the time. Keep an eye on the clock and pull the roast out after a set amount of time has passed. This allows you to do other things (prep and cook the vegetables, set the table, etc) while waiting for the roast to finish. Robin2 actually has a really good sketch that does a better job demonstrating (both in complexity and with technique) BWoD in this thread.

Don't forget to show your appreciation with the karma button

I didn't know I could do that. Well your 'karma points' are up now.

Hmmm... temperature sensor, now liquid flow meter... Just out of curiosity, what is the full project? An aquarium monitor? Hot water meter? Thermally triggered water cannon?

Temperature of the exhaust gas from a car. I need to measure the rpm of the wheel as well. So in all, the data I need to capture in real-time are :

  1. Temperature
  2. RPM of the wheel
  3. Flow rate of the exhaust gas

All these should be graphed simultaneously against time.

V_88:

Don't forget to show your appreciation with the karma button

I didn't know I could do that. Well your 'karma points' are up now.

Hmmm... temperature sensor, now liquid flow meter... Just out of curiosity, what is the full project? An aquarium monitor? Hot water meter? Thermally triggered water cannon?

Temperature of the exhaust gas from a car. I need to measure the rpm of the wheel as well. So in all, the data I need to capture in real-time are :

  1. Temperature
  2. RPM of the wheel
  3. Flow rate of the exhaust gas

All these should be graphed simultaneously against time.

Hmmm... exhaust gas flow. Unless you have heard from others that that flow meter is suitable, I'd be concerned. It's rated as a water-flow meter, meaning that it is specifically engineered for a fluid with a similar viscosity to water. Gasses are significantly lower viscosity...

Also, exhaust gasses can be nasty to electronics. First, exhaust gasses are hot. Then, water vapor is a significant portion of exhaust. If allowed to condense the water can cause a whole range of problems, not just because it is liquid water, but also because the liquid water can dissolve other components of the exhaust gas and become caustic, which then can be hot which would increase the caustic reactivity. Additionally, you don't want a flow meter that will reduce your exhaust flow too much putting back-pressure on your engine. The actual flow of exhaust isn't a nice clean linear flow, it comes in pulses. You would need to have a flow meter that can handle the turbulence (either being fast enough to respond and then average it out in software or averages the pulses by design yet not give false reading if a resonant frequency is hit). Yes, the devil really is in the details...

So, you would need a gas-flow meter that can keep liquid water from reaching the electronics and can resist high temperatures and acids. It would need to be engineered for turbulent flow. I'm no expert at flow meters, but you may find something at Omega. You may also be able to get some help from their support staff (email or web-based online chat) to choose an appropriate flow sensor for your task.

I wish you good luck with your project.

Hey, I am thinking this JY209-01 sensor would be a good thing to buy for measuring the RPM of the wheel.

Which would be the best sensor for the RPM measurement of the wheel? Some of them are Hall effect sensors. So which would be the best thing to go with?

V_88:
Hey, I am thinking this JY209-01 sensor would be a good thing to buy for measuring the RPM of the wheel.

Which would be the best sensor for the RPM measurement of the wheel? Some of them are Hall effect sensors. So which would be the best thing to go with?

Well, you would have to figure out where/how to install it. You are really getting out of my wheelhouse with auto sensors. I don't suppose the car has an ODB-II interface? If so there might be a sensor somewhere already on the wheel train that you could tap into. An auto gear-head would have better answers for you.

Maybe start a thread on the Sensors forum to see if anyone there has experience picking out a sensor both for wheel RPM and the exhaust. Don't cross-post your questions on multiple forums though. Many people read multiple forums and they don't need to see your question many times.

An auto gear-head would have better answers for you.

Maybe start a thread on the Sensors forum

I don't think the car I am going to work with (haven't even seen it yet), has an ODB-II interface. By Sensors forum do you mean here or in another site like this? I was following this http://forum.arduino.cc/index.php/topic,92624.0.html

But I don't want to use a mechanical switch, I believe an IR sensor pair would be better.

V_88:

An auto gear-head would have better answers for you.

Maybe start a thread on the Sensors forum

I don't think the car I am going to work with (haven't even seen it yet), has an ODB-II interface. By Sensors forum do you mean here or in another site like this? I was following this http://forum.arduino.cc/index.php/topic,92624.0.html

But I don't want to use a mechanical switch, I believe an IR sensor pair would be better.

Yes, I mean the sensor forum here on the Arduino site at: Sensors - Arduino Forum

I agree about conceptually wanting to avoid a mechanical switch. A stationary (relative to the suspension) hall effect sensor with a magnet mounted to the wheel or axle should work. Potentially an IR sensor pair with a white/reflective spot on the wheel or axle should also work, but might have issues if the white/reflective spot picks up dirt and/or road grime. Maybe look at the RPM of the drive shaft between the transmission and the differential (assuming rear-wheel drive and sensing desired on the drive wheels instead of the slave wheels...) since there should be less motion trying to knock your sensor arrangement out of whack and tugging on the rest of your wiring. Again, another assumption that this whole sensor bit is being (semi?) permanently mounted to the vehicle frame and using the XBees as a virtual umbilical. Maybe tapping off of the speedometer sensor wires near the computer or dashboard would be cleaner. Even if the speedometer is mechanical (like in my old '72 bug), the 'cleanest' (i.e. most resistant to dirt and grime) solution would be to put the rotational sensor inside the speedometer, sensing where the rotating cable linked to the wheel comes into the speedometer.

You can see that it can be hard to give advice or make final design decisions without very detailed information about the expected environment. I feel for you since you don't even know exactly what car will be used so you can't finalize some of your own design elements yet (like exactly how and where things will be mounted, how long sensor cables need to be, etc.). Location and type of speedometer sensor to exploit also can't be known until year, make, and model of the vehicle is known...

Wait... No ODB-II? How old do you expect this vehicle to be? All cars sold in the US since '96 must have ODB-II, and if you are in Europe, WikiPedia (yeah, I know...) says: "The EOBD (European On Board Diagnostics) regulations are the European equivalent of OBD-II, and apply to all passenger cars of category M1 (with no more than 8 passenger seats and a Gross Vehicle Weight rating of 2500 kg or less) first registered within EU member states since January 1, 2001 for petrol (gasoline) engined cars and since January 1, 2004 for diesel engined cars."
So, if the car you get to work on doesn't have some variant of ODB-II, the youngest would be a European diesel that is over 10 years old...

Again, another assumption that this whole sensor bit is being (semi?) permanently mounted to the vehicle frame and using the XBees as a virtual umbilical. Maybe tapping off of the speedometer sensor wires near the computer or dashboard would be cleaner.

Okay. I guess I will go with that method then.

Hey Sembazuru,

I wanted to ask about this. I found a MAF sensor, and I am thinking this is more suited to my application than the MLX90614.

If I understand it correctly it measures the temperature and the flow rate right?

V_88:
Hi Sembazuru,

I want to thank you for guiding me through the XBee code. However, this is not over. My project needs me to measure RPM and also the exhaust gas flow rate.

I am not finding any sensors which can be interfaced with Arduino, and which can withstand the temperatures of the exhaust gas for the flow rate measurement.

For the RPM, I ordered the Hall effect sensor A3144.

Here is the link from Ebay :
http://www.ebay.com/itm/like/251114199126?lpid=82

I guess I could use the digital pins on the board for this one. But do you have any ideas for the flow measurement?

V_88:
Hey Sembazuru,

I wanted to ask about this. I found a MAF sensor, and I am thinking this is more suited to my application than the MLX90614.

If I understand it correctly it measures the temperature and the flow rate right?

http://www.farnell.com/datasheets/1765755.pdf

A MAF sensor might be good for the exhaust but as I've said before, I don't have the experience to be able to tell you exactly what sensor you need. I'd try contacting a sensor vendor (like my suggestion for Omega), or try contacting the manufacturer of a sensor you think might work and have them verify that it would work.

You need to explain to them exactly what you need to measure, and that you will be reading the output of the sensor with a 5V microcontroller with either digital (I2C, SPI, or pulses) or 10bit ADC (I don't know of "Arduino" would mean anything to them). If this is for a school project, mention that and you may get an educational discount.

Remember, for hall effect sensors you need to have a magnet mounted to the moving part that passes close enough to the sensor to trigger it. I understand the theory of hall effect sensors, but I've never set one up. Unfortunately, I'm not sure if you can rely on any technical support from an e-bay retailer. It can't hurt to ask, but I wouldn't expect any. (It's not like DigiKey, Newark, SparkFun, AdaFruit, etc. that have engineers on staff to assist with customer technical support.)

That hall effect sensor that you mentioned, I haven't dug up a manufacturer's datasheet on it yet (look up the part number on Octopart, and you should find one), but if the e-bay description is true it needs 24V to power it. I would expect the output signal to potentially be greater than the 5V allowed by the Arduino, and 24V is more than is normally available on cars so you would have provide a power supply on the car for it instead of using the car's existing power supply (the battery) passed through a regulator to lock at a voltage less than 12V to provide a stable voltage instead of the 12-14V that the battery/alternator puts out.

I've been thinking... Wheel RPM? Are you sure it isn't engine RPM? Because of the transmission those two things are completely different...

Hey sorry for the delay in my response. I haven't had the time to log in here. Its wheel RPM we want to measure now.