Serial.parseFloat() считывает 0, несмотря на то, что я ввел другое значение

Я пытаюсь создать робота, который спрашивает у пользователя долготу и высоту, а затем использует собранные GPS данные, чтобы добраться до нужного места. Однако, когда я использую Serial.parseFloat(), чтобы получить местоположение от пользователя, я получаю правильное значение широты, а долгота почему-то возвращает ноль. вот код, который я написал

#include "Adafruit_FONA.h"

// стандартные штифты для щита, при необходимости отрегулируйте
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
#define PIN13 13
#define IN1 6      //IN1
#define IN2 7        //IN2
#define ENA 5          //ENA
#define ENB 10        //ENB
#define IN3 8          //IN3
#define IN4 9          //IN4
#define trigger1 A3      //Триггер
#define echo1 A2        //Эхо
#define trigger2 A4
#define echo2 A5
#define trigger3 A0
#define echo3 A1

// Мы по умолчанию используем программный последовательный порт. Если вы хотите использовать аппаратный последовательный порт
// (т.к. softserial не поддерживается) закомментируйте следующие три строки
// и раскомментируйте строку HardwareSerial
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
int counter;
char serialData;
int duration;
float distance1, distance2, distance3;
float latitudeDestination, longitudeDestination;

// Аппаратный последовательный порт также возможен!
// Аппаратный последовательный порт *fonaSerial = &Serial1;
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
// У вас есть FONA 3G? используйте вместо этого этот тип объекта
//Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);

void getLatitude(){
    Serial.println("Enter the latitude destination :");
    while (Serial.available() == 0){}
    latitudeDestination = Serial.parseFloat();
}

void getLongitude()
{
    Serial.println("Enter the longitude destination :");
    while (Serial.available() == 0){}
    longitudeDestination = Serial.parseFloat(); 
}

void securityPassed()
{
    Serial.println("You need to pass security first");
    while (Serial.available() ==0){}
    serialData = Serial.read();
    if (serialData == '1')
    {
        Serial.println("Passed") ;
    }
    else {}
}

void setup() {
    pinMode(PIN13, INPUT);
    pinMode(trigger1, OUTPUT);
    pinMode(echo1, INPUT);
    pinMode(trigger2, OUTPUT);
    pinMode(echo2, INPUT);
    pinMode(trigger3, OUTPUT);
    pinMode(echo3, INPUT);
    pinMode(IN1 , OUTPUT);
    pinMode(IN2, OUTPUT);
    pinMode(IN3, OUTPUT);
    pinMode(IN4, OUTPUT);
    pinMode(ENA, OUTPUT);
    pinMode(ENB, OUTPUT);

    digitalWrite(ENA , HIGH);
    digitalWrite(ENB, HIGH);

    Serial.begin(9600);

    getLatitude();
    getLongitude();
    securityPassed();

    Serial.println(F("Adafruit FONA 808 & 3G GPS demo"));
    Serial.println(F("Initializing FONA... (May take a few seconds)"));
    fonaSerial->begin(4800);
    if (! fona.begin(*fonaSerial)) {
        Serial.println(F("Couldn't find FONA"));
        while (1);
    }
    Serial.println(F("FONA is OK"));
    // Попробуйте включить GPRS
    Serial.println(F("Enabling GPS..."));
    fona.enableGPS(true);
}

void loop() {
    delay(2000);

    float latitude, longitude, speed_kph, heading, speed_mph, altitude;
    float latitudeDistance = latitudeDestination - latitude ;
    float longitudeDistance = longitudeDestination - longitude;

    // если вы запросите показания высоты, getGPS вернет false, если 3D-фиксации нет
    boolean gps_success = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
    if (gps_success) {
      Serial.print("GPS lat:");
      Serial.println(latitude, 6);
      Serial.print("GPS long:");
      Serial.println(longitude, 6);
      Serial.print("GPS speed KPH:");
      Serial.println(speed_kph);
      Serial.print("GPS speed MPH:");
      speed_mph = speed_kph * 0.621371192;
      Serial.println(speed_mph);
      Serial.print("GPS heading:");
      Serial.println(heading);
      Serial.print("GPS altitude:");
      Serial.println(altitude);
      Serial.print("Latitude Distance: ");
      Serial.println(latitudeDistance);
      Serial.print("Longitude Distance: ");
      Serial.println(longitudeDistance);

      if ( latitudeDistance < 0.00001 && latitudeDistance > -0.00001)
      {

        if ( longitudeDistance < 0.00001 && longitudeDistance > -0.00001)
        {
          Serial.print("Arrived");
          stopm();
        }
        else
        {
          if (!counter == 1 && longitudeDistance > 0 )
          {
            moveRight();
            Serial.println("Turning Right");
            counter =1;
          }
          else if ( !counter == 1 && longitudeDistance < 0 )
          {
            moveLeft();
            Serial.println("Turning Left");
            counter=1;

          }
          moveForward();
        }
      }
      else
      {
        moveForward();
        Serial.print("Going To Destination");
      }
    }
    else {
      Serial.println("Waiting for FONA GPS 3D fix...");
    }
}

, 👍2


1 ответ


Лучший ответ:

2

Конечно, вполне возможно, что человек, печатающий текст (или автоматизированная система, передающая данные в пакетах по нестабильной связи), не сможет предоставить допустимое число за время (по умолчанию 1 секунда) до истечения времени ожидания parseFloat().

Однако, учитывая, что это второе значение, которое нужно прочитать, существует более сложная возможность.

Вероятно, фактически отправленная последовательность может быть чем-то вроде

123.45\r\n

В этом случае 123.45 и первый незначимый символ \r будут использованы первым parseFloat().

Но это оставляет оставшийся \n в последовательном буфере, поэтому проверка serialAvailable() выполняется немедленно, а следующий parseFloat() начинается до того, как пользователь начал печатать. Если только он не ответит очень быстро, время ожидания может истечь еще до того, как он начнет.

Если предполагается, что пользователь будет использовать терминальную программу, которая отправляет возврат каретки и/или новую строку, вам, вероятно, следует изменить обработку ввода, чтобы она либо обрабатывалась до конца строки, либо обрабатывалась.

Или вы можете сделать свой код гибким, убедившись, что все конечные символы конца строки учтены (после проверки на них с помощью Serial.peek()) до того, как вы решите, что пользователь начал вводить новое значение, и начнете следующий вызов parseFloat().

Вы также можете создать свой собственный, более сложный parseFloat(), используя другой алгоритм.

,