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模块采用了ModuleBase和WorkQueue设计。
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模块的主要内容,如果未能解决你的问题,请参考以下文章