• PX4模块设计之二十四:内部ADC模块


    1. 内部ADC模块简介

    该模块在ModuleBase基础命令上,新增定制test测试各个ADC通道采集的原始数据。

    ### Description
    ADC driver.
    
    adc  [arguments...]
     Commands:
       start
    
       test
         [-n]        Do not publish ADC report, only system power
    
       stop
    
       status        print status info
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注:print_usage函数是具体对应实现。

    class ADC : public ModuleBase, public px4::ScheduledWorkItem
    
    • 1

    注:ADC模块采用了ModuleBaseWorkQueue设计。

    2. 模块入口函数

    2.1 主入口board_adc_main

    board_adc_main
     └──> return ADC::main(argc, argv);
    
    • 1
    • 2

    2.2 自定义子命令custom_command

    ADC::custom_command
     ├──> 
     │   └──> return _object.load()->test()
     └──> return print_usage("unknown command")
    
    • 1
    • 2
    • 3
    • 4

    内部调用了测试函数test进行20次ADC数据更新(第一次)。

    ADC::test
     ├──> px4_usleep(20000)  //等待20ms
     ├──> 
     │   └──> return 1
     ├──> PX4_INFO_RAW("DeviceID: %" PRId32 "\n", adc.device_id)
     ├──> PX4_INFO_RAW("Resolution: %" PRId32 "\n", adc.resolution)
     ├──> PX4_INFO_RAW("Voltage Reference: %f\n", (double)adc.v_ref)
     ├──>                // 更新20次ADC数据
     │   ├──>   // 将所有ADC有效通道进行原始数据更新
     │   │   └──> = 0>
     │   │       └──> PX4_INFO_RAW("% 2" PRId16 " :% 6" PRId32, adc.channel_id[i], adc.raw_data[i])
     │   ├──> PX4_INFO_RAW("\n")
     │   └──> px4_usleep(500000)  //等待500ms
     ├──> PX4_INFO_RAW("\t ADC test successful.\n")
     └──> return 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3. 内部ADC模块重要函数

    3.1 task_spawn

    内部ADC模块采用了PX4 WorkQueue机制

    ADC::task_spawn
     ├──> ADC *instance = new ADC(SYSTEM_ADC_BASE, ADC_CHANNELS)
     ├──> 
     │   ├──> _object.store(instance)
     │   ├──> _task_id = task_id_is_work_queue   // PX4 WorkQueue机制
     │   └──> init() == PX4_OK>
     │       └──> return PX4_OK
     ├──> 
     │   └──> PX4_ERR("alloc failed")
     ├──> delete instance
     ├──> _object.store(nullptr)
     ├──> _task_id = -1
     └──> return PX4_ERROR
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    内部ADC模块实际上使用了3个通道来检测电压,电流和RSSI ADC模拟信号。

    #define ADC_CHANNELS \
    	((1 << ADC_BATTERY_VOLTAGE_CHANNEL)       | \
    	 (1 << ADC_BATTERY_CURRENT_CHANNEL)       | \
    	 (1 << ADC_RSSI_IN_CHANNEL))
    
    • 1
    • 2
    • 3
    • 4

    3.2 instantiate

    注:鉴于该模块不采用任务(线程),所以ModuleBase::run_trampoline无需执行,所以可以不实现。

    3.3 init

    内部ADC模块数据采样间隔10ms(100Hz)。

    ADC::init
     ├──> int ret_init = px4_arch_adc_init(_base_address)
     ├──> 
     │   ├──> PX4_ERR("arch adc init failed")
     │   └──> return ret_init
     ├──> ScheduleOnInterval(kINTERVAL, kINTERVAL)  // // schedule regular updates, 10ms
     └──> return PX4_OK
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.4 Run

    当ScheduleOnInterval时间一到,HRT模块将会新增一个WorkQueue,此时WorkQueue会调用Run函数。

    ADC::Run
     ├──> <_first_run>
     │   ├──> open_gpio_devices()
     │   └──> _first_run = false
     ├──> hrt_abstime now = hrt_absolute_time()
     ├──> 
     │   └──> _samples[i].am_data = sample(_samples[i].am_channel)   //对每个通道进行数据采集
     ├──> update_adc_report(now)
     └──> update_system_power(now)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.5 sample

    ADC::sample
     ├──> perf_begin(_sample_perf)
     ├──> uint32_t result = px4_arch_adc_sample(_base_address, channel)
     ├──> 
     │   └──> PX4_ERR("sample timeout")
     ├──> perf_end(_sample_perf)
     └──> return result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.6 其他函数

    【1】void ADC::update_adc_report(hrt_abstime now)
    【2】void ADC::update_system_power(hrt_abstime now)

    注:这里的接和uORB主题相关的消息发布函数,主要是将ADC模块的数据通过消息总线向PX4系统发布,让订阅这些主题的应用获取最新ADC数据。

    4. 总结

    基于PX4应用平台的HRT、WorkQueue、ModuleBase三个基础组件,ADC模块整体看上去并不复杂,且也易于理解。

    注1:adc_report主要是MCU使用ADC管脚对ADC_BATTERY_VOLTAGE_CHANNEL、ADC_BATTERY_CURRENT_CHANNEL、ADC_RSSI_IN_CHANNEL三个通道进行数据采集。
    注2:system_power主要针对飞控USB供电的情况所报告的系统电压,holybo_kakutef7板子就未使能这个功能。

    5. 参考资料

    【1】PX4开源软件框架简明简介
    【2】PX4模块设计之十一:Built-In框架
    【3】PX4模块设计之十二:High Resolution Timer设计
    【4】PX4模块设计之十三:WorkQueue设计
    【5】PX4模块设计之十七:ModuleBase模块
    【6】PX4 modules_main

  • 相关阅读:
    win11-qt5.14配置
    Google Earth Engine(GEE) 03-矢量数据类型
    苹果使用3D打印技术制造Apple Watch Series 9手表外壳
    kafka操作的一些坑
    【HDU No. 5057】序列操作 Argestes and Sequence
    台达PLC和昆仑通态触摸屏通讯设置
    STM32F407 电机编码器测量
    Jmeter和Postman那个工具更适合做接口测试?
    PyTorch实现DCGAN(生成对抗网络)生成新的假名人照片实战(附源码和数据集)
    [CVPR2022] Debiased Learning from Naturally Imbalanced Pseudo-Labels
  • 原文地址:https://blog.csdn.net/lida2003/article/details/126340843