LCOV - code coverage report
Current view: top level - AP_RangeFinder - AP_RangeFinder_analog.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 29 47 61.7 %
Date: 2026-09-09 11:02:08 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : 
      16             : /*
      17             :  *   AP_RangeFinder_analog.cpp - rangefinder for analog source
      18             :  *
      19             :  */
      20             : 
      21             : #include "AP_RangeFinder_analog.h"
      22             : 
      23             : #if AP_RANGEFINDER_ANALOG_ENABLED
      24             : 
      25             : #include <AP_HAL/AP_HAL.h>
      26             : #include <AP_Common/AP_Common.h>
      27             : #include <AP_Math/AP_Math.h>
      28             : #include "AP_RangeFinder.h"
      29             : #include "AP_RangeFinder_Params.h"
      30             : 
      31             : extern const AP_HAL::HAL& hal;
      32             : 
      33             : /* 
      34             :    The constructor also initialises the rangefinder. Note that this
      35             :    constructor is not called until detect() returns true, so we
      36             :    already know that we should setup the rangefinder
      37             : */
      38         130 : AP_RangeFinder_analog::AP_RangeFinder_analog(RangeFinder::RangeFinder_State &_state, AP_RangeFinder_Params &_params) :
      39         130 :     AP_RangeFinder_Backend(_state, _params)
      40             : {
      41         130 :     source = hal.analogin->channel(_params.pin);
      42         130 :     if (source == nullptr) {
      43             :         // failed to allocate a ADC channel? This shouldn't happen
      44           0 :         set_status(RangeFinder::Status::NotConnected);
      45           0 :         return;
      46             :     }
      47         130 :     set_status(RangeFinder::Status::NoData);
      48             : }
      49             : 
      50             : /* 
      51             :    detect if an analog rangefinder is connected. The only thing we
      52             :    can do is check if the pin number is valid. If it is, then assume
      53             :    that the device is connected
      54             : */
      55         130 : bool AP_RangeFinder_analog::detect(AP_RangeFinder_Params &_params)
      56             : {
      57         130 :     if (_params.pin != -1) {
      58         130 :         return true;
      59             :     }
      60           0 :     return false;
      61             : }
      62             : 
      63             : 
      64             : /*
      65             :   update raw voltage state
      66             :  */
      67      162019 : void AP_RangeFinder_analog::update_voltage(void)
      68             : {
      69      162019 :    if (source == nullptr || !source->set_pin(params.pin)) {
      70           0 :        state.voltage_mv = 0;
      71           0 :        set_status(RangeFinder::Status::NotConnected);
      72           0 :        return;
      73             :    }
      74      162019 :    if (params.ratiometric) {
      75      162019 :        state.voltage_mv = source->voltage_average_ratiometric() * 1000U;
      76             :    } else {
      77           0 :        state.voltage_mv = source->voltage_average() * 1000U;
      78             :    }
      79             : }
      80             : 
      81             : /*
      82             :   update distance_cm 
      83             :  */
      84      162019 : void AP_RangeFinder_analog::update(void)
      85             : {
      86      162019 :     update_voltage();
      87      162019 :     float v = state.voltage_mv * 0.001f;
      88      162019 :     float dist_m = 0;
      89      162019 :     float scaling = params.scaling;
      90      162019 :     float offset  = params.offset;
      91      162019 :     RangeFinder::Function function = (RangeFinder::Function)params.function.get();
      92      162019 :     const float _max_distance = max_distance();
      93             : 
      94      162019 :     switch (function) {
      95      162019 :     case RangeFinder::Function::LINEAR:
      96      162019 :         dist_m = (v - offset) * scaling;
      97      162019 :         break;
      98             :           
      99           0 :     case RangeFinder::Function::INVERTED:
     100           0 :         dist_m = (offset - v) * scaling;
     101           0 :         break;
     102             : 
     103           0 :     case RangeFinder::Function::HYPERBOLA:
     104           0 :         if (v <= offset) {
     105           0 :             dist_m = 0;
     106             :         } else {
     107           0 :             dist_m = scaling / (v - offset);
     108             :         }
     109           0 :         if (dist_m > _max_distance) {
     110           0 :             dist_m = _max_distance;
     111             :         }
     112           0 :         break;
     113             :     }
     114      162019 :     if (dist_m < 0) {
     115           0 :         dist_m = 0;
     116             :     }
     117      162019 :     state.distance_m = dist_m;
     118      162019 :     state.last_reading_ms = AP_HAL::millis();
     119             : 
     120             :     // update range_valid state based on distance measured
     121      162019 :     update_status();
     122      162019 : }
     123             : 
     124             : #endif  // AP_RANGEFINDER_ANALOG_ENABLED

Generated by: LCOV version 1.14