Currently i success to build the communication between the android device and arduino through bluetooth. As arduino will send string "ON" or "OFF" depend on the LED condition to Android through bluetooth and my android able to receive the string "LED:ARE:OFF" and "LED:ARE:ON" through the read() function. But currently i want to read a data by split the string into 3 from the LED, for example: "LED:ARE:OFF" into "LED" , "Are", "OFF" , but i failed to received the data. I had tried the String.split(":") to split out the aaa:bbb:ccc into 3 part, and it unable to read the data as well. Please help
Arduino Code:
#include <SoftwareSerial.h>// import the serial library
SoftwareSerial Genotronex(10, 11); // RX, TX
int ledpin=8; // led on D13 will show blink on / off
long previousMillis = 0; // will store last time LED was updated
long interval = 1000; // interval at which to blink (milliseconds)
int ledState = LOW; // ledState used to set the LED
long Counter=0; // counter will increase every 1 second
void setup() {
// put your setup code here, to run once:
Genotronex.begin(9600);
Genotronex.println("Bluetooth On please wait....");
pinMode(ledpin,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
Counter+=1;
delay(4000);
// if the LED is off turn it on and vice-versa:
if (ledState == LOW){
ledState = HIGH;
Genotronex.print("LED:ARE:ON");
digitalWrite(ledpin, ledState);
}
else{
ledState = LOW;
Genotronex.print("LED:ARE:OFF");
digitalWrite(ledpin, ledState);
}
// set the LED with the ledState of the variable:
}
}
Android Code:
btnSend.setOnClickListener(this);
int delay = 1000; // delay in ms
int period = 100; // repeat in ms
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
if (flag)
{
final byte data = read();
readMessageHandler.post(new Runnable()
{
public void run()
{
if (data != 1){
message = txtReceived.getText().toString() + (char)data;}
else{
message = "";
}
String message;
//New Code for split the data
String[] parts = message.split(":"); // escape .
String part0 = parts[0];
String part1 = parts[1];
String part2 = parts[2];
txtReceived.setText(part0);
//End of Split
// txtReceived.setText(Message);
}
});
}
}
}, delay, period);
private byte read()
{
byte dataRead = 0;
try
{
dataRead = (byte) inputStream.read();
}
catch(IOException readException)
{
toastText = "Failed to read from input stream: " + readException.getMessage();
Toast.makeText(Blood_Pressure.this, toastText, Toast.LENGTH_SHORT).show();
}
return dataRead;
}
Related
I want that the measurement interval and MQTT server settings can be changed from cellphone by BLE. I use LightBlue as a mobile application.
Here is my BLE code that works well with my mobile application
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE scanner app in your phone");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to MyESP32");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
Serial.println("5- See the magic =)");
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
This is MQTT code :
void loop() {
unsigned long currentMillis = millis();
// Every X number of seconds (interval = 10 seconds)
// it publishes a new MQTT message
if (currentMillis - previousMillis >= interval) {
// Save the last time a new reading was published
previousMillis = currentMillis;
// New DHT sensor readings
hum = dht.readHumidity();
// Read temperature as Celsius (the default)
temp = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//temp = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(temp) || isnan(hum)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Publish an MQTT message on topic esp32/dht/temperature
uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId: %i", MQTT_PUB_TEMP, packetIdPub1);
Serial.printf("Message: %.2f \n", temp);
// Publish an MQTT message on topic esp32/dht/humidity
uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUM, 1, true, String(hum).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_HUM, packetIdPub2);
Serial.printf("Message: %.2f \n", hum);
}
}
Please how I can set the interval to whichever variable from the BLE code instead of 10000.
long interval = 10000;
You need to declare your variable interval as global variable to access it from everywhere in your file. A global variable can be declared outside of functions.
The value you receive is of type std::string and you want to use it as long. You can use toInt() to convert the variable from String to Long.
Try something like this:
long interval = 10000; // Set default value
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
interval = value.toInt(); // <-- Set received value
}
}
};
I work with interruptions in Arduino UNO. In this project, I want to when the Door is opened the LED blink 10 times, and when the door is closed again, stop blinking the LED and exit the function. But in this code the LED only turn on and off once and it does not flash again.
My other problem is that, when the door is opened or closed, sometimes the opened or closed word appears several times in the Series monitor.
const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin
volatile int SensorState = LOW; // 0 close - 1 open wwitch
void setup()
{
Serial.begin(9600);
pinMode(LED_Red, OUTPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}
void DoAction()
{
SensorState = digitalRead(DOOR_SENSOR);
if (SensorState == HIGH) {
Serial.println("Opened");
blinkLED(10, 500);
}
else {
Serial.println("Closed");
}
}
void blinkLED(int repeats, int time)
{
for (int i = 0; i < repeats; i++) {
if (SensorState == HIGH) {
digitalWrite(LED_Red, HIGH);
delay(time);
digitalWrite(LED_Red, LOW);
delay(time);
}
else
return;
}
}
void loop()
{
}
You can't simply put a delay() on an interrupt's function. You need to just set a flag when the door is opened and based on that start blinkLED inside the main loop.
I also recommend you to use millis() function for an unblocking delay inside blinkLED function (e.g when you want to stop blinking while the door is closed).
const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin
// flag to check door is opened
volatile bool isOpened = false;
//flag to check already blinked
volatile bool isBlinked = false;
void setup()
{
Serial.begin(9600);
pinMode(LED_Red, OUTPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}
void DoAction()
{
if (digitalRead(DOOR_SENSOR) == HIGH)
{
//Serial.println("Opened");
isOpened = true;
}
else
{
isOpened = false;
isBlinked = false;
//Serial.println("Closed");
}
}
void blinkLED(int repeats, int time)
{
byte LEDState = LOW;
unsigned long delay_start = millis();
for (int i = 0; i < 2 * repeats; i++)
{
//Toggle LED state
if (LEDState == HIGH)
LEDState = LOW;
else
LEDState = HIGH;
// set value
digitalWrite(LED_Red, LEDState);
// some unblocking delay
while (millis() - delay_start < time)
{
// return if door is closed
if (!isOpened)
{
// turn off LED
digitalWrite(LED_Red, LOW);
return;
}
}
delay_start = millis();
}
isBlinked = true;
}
void loop()
{
// Check isBlinked beacue don't want to blink again until door is closed
if (isOpened && !isBlinked)
{
blinkLED(10, 500);
}
}
I'm trying to see if I can combine tasks that are currently being handled by two separate Arduino Unos onto a single Uno. I was shown the Adafruit guide to "multi-tasking" on the Arduino (Link) and thought I would give it a try.
I feel like I'm missing something really obvious, but my code is just not working...
I'm controlling a series of solenoids. They need to each act based on individual timing. I created a Solenoid class that handles telling the solenoid when to start and then monitor when to close it. For the life of me I can't see where my error is, but I never wind up satisfying my end condition.
class Solenoid {
//Class Variables
int solenoidPin;
long chargeTime;
long ventTime;
bool started = false;
unsigned long startMillis;
unsigned long endMillis;
unsigned long previousMillis;
int solenoidState;
//Constructor
public:
Solenoid(int pin, long charge, long vent) {
solenoidPin = pin;
pinMode(solenoidPin, OUTPUT);
chargeTime = charge;
ventTime = vent;
solenoidState = LOW;
previousMillis = 0;
}
void Start() {
Serial.println("Start called");
started = true;
}
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
Serial.println("Update");
if((started == true) && (currentMillis-previousMillis <= chargeTime)) {
//Run
Serial.print("Run: Charge Time=");
Serial.print(chargeTime);
Serial.print(" current-previous=");
Serial.println(currentMillis-previousMillis);
previousMillis = currentMillis;
} else if ((started == true) && (currentMillis-previousMillis >= chargeTime)){
//Stop
Serial.println("Stop");
}
}
};
//Setup the solenoids
Solenoid solenoid1(13, 70, 70);
void setup() {
Serial.begin(115200);
Serial.println("Ready");
solenoid1.Start();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
}
I'm just running everything in setup so I can see a few runs.
Can you help me with my clearer stupid mistake?
It's possible that the entire setup() void is executing faster than 70ms, meaning you never get to you end position before the 5 calls to solenoid1.Update() complete.
Try this:
class Solenoid {
//Class Variables
int solenoidPin;
long chargeTime;
long ventTime;
bool started = false;
unsigned long startMillis;
unsigned long endMillis;
unsigned long previousMillis;
int solenoidState;
//Constructor
public:
Solenoid(int pin, long charge, long vent) {
solenoidPin = pin;
pinMode(solenoidPin, OUTPUT);
chargeTime = charge;
ventTime = vent;
solenoidState = LOW;
previousMillis = 0;
}
void Start() {
Serial.println("Start called");
started = true;
}
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
Serial.println("Update");
if((started == true) && (currentMillis-previousMillis <= chargeTime)) {
//Run
Serial.print("Run: Charge Time=");
Serial.print(chargeTime);
Serial.print(" current-previous=");
Serial.println(currentMillis-previousMillis);
previousMillis = currentMillis;
} else if ((started == true) && (currentMillis-previousMillis >= chargeTime)){
//Stop
Serial.println("Stop");
}
}
};
//Setup the solenoids
Solenoid solenoid1(13, 70, 70);
void setup() {
Serial.begin(115200);
Serial.println("Ready");
solenoid1.Start();
}
void loop(){
solenoid1.update()
}
The rest looks fine to me; if you still have issues try using explicit variable declarations instead of your constructor to troubleshoot if that's the issue.
Turns out I was erasing my own counter by setting previousMillis = currentMillis. Once I killed that, it started working. I added some other functionality since then, like a delayed start, but this is primarily the same code.
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
if((started == true) && (currentMillis - startMillis <= startDelay)) {
//keep waiting
Serial.println("Waiting");
} else if((started == true) && (currentMillis - startMillis < (chargeTime + startDelay) )) {
//Run
Serial.print("Run ");
Serial.println(currentMillis - startMillis);
digitalWrite(solenoidPin, HIGH);
} else if ((started == true) && (currentMillis - startMillis >= (chargeTime + startDelay) )){
//Stop
Serial.print("Stop ");
Serial.println(currentMillis - startMillis);
digitalWrite(solenoidPin, LOW);
started = false;
}
}
I'm trying to pass multiple variables (n number of strings and n number of ints) from processing to my Arduino. I found this tutorial online and managed to send a single value. Now I have two arrays that both need to be accessed by the Arduino filesTypes[] and filesSizes[]. filesTypes[] consists of a 3 char long strings while fileSizes[] is an array of different integers.
Here is my Processing code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
String[] fileTypes;
int[] fileSizes;
String[][] lines;
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[1]; //change the 0 to a 1 or 2 etc. to
match your port
myPort = new Serial(this, portName, 9600);
launch( sketchPath("") + "/test.bat");
}
void draw() {
if (mousePressed == true)
{ //if we clicked in the window
txtToStrg();
myPort.write('1'); //send a 1
txtToStrg();
} else
{ //otherwise
myPort.write('0'); //send a 0
}
}
void txtToStrg(){
String[] lines = loadStrings("list.txt");
fileTypes = new String[lines.length];
fileSizes = new int[lines.length];
for (int i = 0 ; i < lines.length; i++) {
if(lines[i] != null) {
String[] splitLine = split(lines[i], ' ');
fileTypes[i] = splitLine[0];
fileSizes[i] = int(splitLine[1]);
println(fileTypes[i] + " = " + fileSizes[i]);
}
}
}
And here my Arduino code:
char val; // Data received from the serial port
int ledPin = 4 ; // Set the pin to digital I/O 13
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
if (Serial.available())
{ // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == '1')
{ // If 1 was received
digitalWrite(ledPin, HIGH); // turn the LED on
} else {
digitalWrite(ledPin, LOW); // otherwise turn it off
Serial.print(val);
}
delay(10); // Wait 10 milliseconds for next reading
}
If a pass anything but a char it stops working.
Consider:
String cmdData; // Store the complete command on one line to send to sensor board.
String phResponse; // Store the pH sensor response.
boolean startOfLine = false;
boolean endOfLine = false;
boolean stringComplete = false;
void setup()
{
Serial.begin(38400);
Serial3.begin(38400);
pinMode(2, OUTPUT); // Used for temperature probe
}
void loop()
{
if (stringComplete)
{
Serial.println("Stored Response: " + phResponse);
phResponse = ""; // Empty phResponse variable to get
// ready for the next response
stringComplete = false;
}
}
void serialEvent()
{
while (Serial.available())
{
char cmd = (char)Serial.read();
if (cmd == '{')
{
startOfLine = true;
}
if (cmd == '}')
{
endOfLine = true;
}
if (startOfLine && cmd != '{' && cmd != '}')
{
cmdData += cmd;
}
if (startOfLine && endOfLine)
{
startOfLine = false;
endOfLine = false;
cmdData.toLowerCase(); // Convert cmdData value to lowercase
// for sanity reasons
if (cmdData == "ph")
{
delay(500);
ph();
}
if (cmdData == "phatc")
{
delay(500);
phATC();
}
cmdData = ""; // Empty cmdData variable to get ready for the next command
}
}
}
void serialEvent3()
{
while(Serial3.available())
{
char cmd3 = (char)Serial3.read();
phResponse += String(cmd3);
if (cmd3 == '\r')
{
stringComplete = true;
Serial.println("Carriage Command Found!");
}
}
}
float getTemp(char tempType)
{
float v_out; // Voltage output from temperature sensor
float temp; // The final temperature is stored here (this is only for code clarity)
float tempInCelcius; // Stores temperature in °C
float tempInFarenheit; // Stores temperature in °F
digitalWrite(A0, LOW); // Set pull-up resistor on analog pin
digitalWrite(2, HIGH); // Set pin 2 high, this will turn on temperature sensor
delay(2); // Wait 1 ms for temperature to stabilize
v_out = analogRead(0); // Read the input pin
digitalWrite(2, LOW); // Set pin 2 low, this will turn off temperature sensor
v_out *=. 0048; // Convert ADC points to voltage [volts] (we are using .0048
// because this device is running at 5 volts)
v_out *= 1000; // Convert unit from volts to millivolts
tempInCelcius = 0.0512 * v_out -20.5128; // The equation from millivolts to temperature
tempInFarenheit = (tempInCelcius * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
if (tempType == 'c')
{
return tempInCelcius; // Return temperature in Celsius
}
else if (tempType == 'f')
{
return tempInFarenheit; // Return temperature in Fahrenheit
}
}
void ph()
{
Serial.println("Calculating pH sensor value in 3 seconds");
delay(3000);
Serial3.print("r\r");
}
void phATC()
{
Serial.println("pH auto temperature calibration will start in 3 seconds");
delay(3000);
float temp = getTemp('c');
char tempAr[10];
String tempAsString;
String tempData;
dtostrf(temp, 1, 2, tempAr);
tempAsString = String(tempAr);
tempData = tempAsString + '\r';
Serial3.print(tempData);
}
Why does serialEvent3() trigger after the second and sometimes the third time a command is sent to the sensor board? Once serialEvent3() finally triggers the consecutive commands work fluently. serialEvent() seems to work as expected. I have tried rearranging the functions without success. Is there a 'fail safe' time-out code to send the command again if serialEvent3 is not triggered?
Working code:
String cmdData; // Store the complete command on one line to send to sensor board.
String phResponse; // Store the pH sensor response.
boolean startOfLine = false;
boolean endOfLine = false;
boolean stringComplete = false;
boolean s3Trigger = false;
void setup()
{
Serial3.begin(38400);
Serial.begin(38400);
}
void serialEvent()
{
while (Serial.available())
{
char cmd = (char)Serial.read();
if (cmd == '{')
{
startOfLine = true;
}
if (cmd == '}')
{
endOfLine = true;
}
if (startOfLine && cmd != '{' && cmd != '}')
{
cmdData += cmd;
//Serial.println(cmdData);
}
}
}
void serialEvent3()
{
while(Serial3.available())
{
char cmd3 = (char)Serial3.read();
phResponse += String(cmd3);
if (cmd3 == '\r') // If carriage return has been found then...
{
stringComplete = true;
}
}
}
void loop()
{
if (startOfLine && endOfLine) // Both startOfLine and endOfLine must
// be true to run the command...
{
startOfLine = false;
endOfLine = false;
s3Trigger = true; // Set the s3Trigger boolean to true to check
// if data on Serial3.available() is available.
runCommand();
}
if (stringComplete)
{
Serial.println("Stored Response: " + phResponse); // Print stored response from the pH sensor.
phResponse = ""; // Empty phResponse variable to get ready for the next response
cmdData = ""; // Empty phResponse variable to get ready for the next command
stringComplete = false; // Set stringComplete to false
s3Trigger = false; // Set s3Trigger to false so it doesn't continuously loop.
}
if (s3Trigger) // If true then continue
{
delay(1000); // Delay to make sure the Serial3 buffer has all the data
if (!Serial3.available()) // If Serial3 available then execute
// the runCommand() function
{
//Serial.println("!Serial3.available()");
runCommand();
}
else
{
s3Trigger = false; // Set s3Trigger to false so it doesn't continuously loop.
}
}
}
void runCommand()
{
cmdData.toLowerCase(); // Convert cmdData value to lowercase
// for sanity reasons
if (cmdData == "ph")
{
ph();
}
}
void ph()
{
Serial.println("Calculating pH sensor value in 3 seconds");
delay(3000);
Serial3.print("r\r");
}
New working code without having to send the command twice:
/*
This software was made to demonstrate how to quickly get your
Atlas Scientific product running on the Arduino platform.
An Arduino MEGA 2560 board was used to test this code.
This code was written in the Arudino 1.0 IDE
Modify the code to fit your system.
**Type in a command in the serial monitor and the Atlas
Scientific product will respond.**
**The data from the Atlas Scientific product will come out
on the serial monitor.**
Code efficacy was NOT considered, this is a demo only.
The TX3 line goes to the RX pin of your product.
The RX3 line goes to the TX pin of your product.
Make sure you also connect to power and GND pins to power
and a common ground.
Open TOOLS > serial monitor, set the serial monitor
to the correct serial port and set the baud rate to 38400.
Remember, select carriage return from the drop down menu
next to the baud rate selection; not "both NL & CR".
*/
String inputstring = ""; // A string to hold incoming data from the PC
String sensorstring = ""; // A string to hold the data
// from the Atlas Scientific product
boolean input_stringcomplete = false; // Have we received all
// the data from the PC
boolean sensor_stringcomplete = false; // Have we received all the data from
// the Atlas Scientific product
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() { // Set up the hardware
// Set up the hardware
Serial.begin(38400); // Set baud rate for the hardware
// serial port_0 to 38400
mySerial.begin(38400);
inputstring.reserve(5); // Set aside some bytes for
// receiving data from the PC
sensorstring.reserve(30); // Set aside some bytes for receiving
// data from Atlas Scientific product
pinMode(12, OUTPUT);
digitalWrite(12, HIGH); // Turn on pull-up resistors
//mySerial.print("i\r");
}
void serialEvent() { // If the hardware serial port_0 receives a char
char inchar = (char)Serial.read(); // Get the char we just received
inputstring += inchar; // Add it to the inputString
if(inchar == '\r') { // If the incoming character is a <CR>, set the flag
input_stringcomplete = true;
}
}
void loop() { // Here we go....
while(mySerial.available())
{
char inchar = (char)mySerial.read(); // Get the char we just received
sensorstring += inchar; // Add it to the inputString
if(inchar == '\r') { // If the incoming character
// is a <CR>, set the flag
sensor_stringcomplete = true;
}
//Serial.print(inchar);
}
if (input_stringcomplete){ // If a string from the PC has been
// received in its entirety
//Serial.print(inputstring);
mySerial.print(inputstring); // Send that string to the Atlas Scientific product
inputstring = ""; // Clear the string:
input_stringcomplete = false; // Reset the flag used to tell if we have
// received a completed string from the PC
}
if (sensor_stringcomplete) { // If a string from the Atlas Scientific
// product has been received in its entirety
Serial.println(sensorstring); // Send that string to to the PC's serial monitor
sensorstring = ""; // Clear the string:
sensor_stringcomplete = false; // Reset the flag used to tell if
// we have received a completed string
// from the Atlas Scientific product
}
}
One thing I noticed (not the cause of the serial read problem). In a microprocessor, floating point math is expensive. It might be worth your while to combine these three lines:
v_out*=.0048;
v_out*=1000;
tempInCelcius = 0.0512 * v_out -20.5128;
into:
tempInCelcius = v_out * 0.24576 -20.2128;
I would also move tempInFarenheit = (tempInCelcius * 9.0)/ 5.0 + 32.0; right into the return statement so the calculation is only done if required. Generally splitting these lines up is encouraged for programming on a PC, but with a microprocessor I tend to compact my code and insert lots of comments.
I had a look at the example code for the sensor and I think I have something you can try. You have a while (Serial.available()) line in here. I can't be certain, but this doesn't look right to me and it might be messing you up. Try removing that block and just doing the read in the event.