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

Posted lida2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PX4模块设计之二十四:内部ADC模块相关的知识,希望对你有一定的参考价值。

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

1. 内部ADC模块简介

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

### Description
ADC driver.

adc <command> [arguments...]
 Commands:
   start

   test
     [-n]        Do not publish ADC report, only system power

   stop

   status        print status info

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

class ADC : public ModuleBase<ADC>, public px4::ScheduledWorkItem

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

2. 模块入口函数

2.1 主入口board_adc_main

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

2.2 自定义子命令custom_command

ADC::custom_command
 ├──> <!strcmp(verb, "test")><is_running()>
 │   └──> return _object.load()->test()
 └──> return print_usage("unknown command")

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

ADC::test
 ├──> px4_usleep(20000)  //等待20ms
 ├──> <!adc_sub_test.update(&adc)>
 │   └──> 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)
 ├──> <for (unsigned l = 0; l < 20; ++l)>               // 更新20次ADC数据
 │   ├──> <for (unsigned i = 0; i < PX4_MAX_ADC_CHANNELS; ++i)>  // 将所有ADC有效通道进行原始数据更新
 │   │   └──> <adc.channel_id[i] >= 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

3. 内部ADC模块重要函数

3.1 task_spawn

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

ADC::task_spawn
 ├──> ADC *instance = new ADC(SYSTEM_ADC_BASE, ADC_CHANNELS)
 ├──> <instance>
 │   ├──> _object.store(instance)
 │   ├──> _task_id = task_id_is_work_queue   // PX4 WorkQueue机制
 │   └──> <instance->init() == PX4_OK>
 │       └──> return PX4_OK
 ├──> <else>
 │   └──> PX4_ERR("alloc failed")
 ├──> delete instance
 ├──> _object.store(nullptr)
 ├──> _task_id = -1
 └──> return PX4_ERROR

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

#define ADC_CHANNELS \\
	((1 << ADC_BATTERY_VOLTAGE_CHANNEL)       | \\
	 (1 << ADC_BATTERY_CURRENT_CHANNEL)       | \\
	 (1 << ADC_RSSI_IN_CHANNEL))

3.2 instantiate

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

3.3 init

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

ADC::init
 ├──> int ret_init = px4_arch_adc_init(_base_address)
 ├──> <ret_init < 0>
 │   ├──> PX4_ERR("arch adc init failed")
 │   └──> return ret_init
 ├──> ScheduleOnInterval(kINTERVAL, kINTERVAL)  // // schedule regular updates, 10ms
 └──> return PX4_OK

3.4 Run

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

ADC::Run
 ├──> <_first_run>
 │   ├──> open_gpio_devices()
 │   └──> _first_run = false
 ├──> hrt_abstime now = hrt_absolute_time()
 ├──> <for (unsigned i = 0; i < _channel_count; i++)>
 │   └──> _samples[i].am_data = sample(_samples[i].am_channel)   //对每个通道进行数据采集
 ├──> update_adc_report(now)
 └──> update_system_power(now)

3.5 sample

ADC::sample
 ├──> perf_begin(_sample_perf)
 ├──> uint32_t result = px4_arch_adc_sample(_base_address, channel)
 ├──> <result == UINT32_MAX>
 │   └──> PX4_ERR("sample timeout")
 ├──> perf_end(_sample_perf)
 └──> return result

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

以上是关于PX4模块设计之二十四:内部ADC模块的主要内容,如果未能解决你的问题,请参考以下文章

PX4模块设计之二十六:BatteryStatus模块

PX4模块设计之二十九:RCUpdate模块

PX4模块设计之二十八:RCInput模块

PX4模块设计之二十五:DShot模块

PX4模块设计之二十二:FlightModeManager模块

PX4模块设计之二十一:uORB消息管理模块