- // 步进电机正反转标志
- extern uint8_t fb_flag;
- // 预定步进数
- extern uint16_t plan_step;
- // 总步数(用来定位最强的位置)
- volatile uint16_t step_all=0;
- // ADC最大值
- uint16_t adc_max=0;
- /*
- Main application
- */
- void main(void) {
- // ADC转换用高、低8位数据
- uint8_t resultHigh=0;
- uint8_t resultLow=0;
- uint16_t result=0;
- double avrs[ADC_AVR_CNT];
- uint8_t idx=0;
- uint16_t avr_result=0; // 本次采集平均值
- // Initialize the device
- SYSTEM_Initialize();
- //Setup ADC
- ADCON0bits.FM = 1; //right justify
- ADCON0bits.CS = 1; //ADCRC Clock
- ADPCH = 0x00; //指定RA0为模拟数据输入通道
- TRISAbits.TRISA0 = 1; //Set RA0 to input
- ANSELAbits.ANSELA0 = 1; //Set RA0 to analog
- ADCON0bits.ON = 1; //Turn ADC On
- // Enable the Global Interrupts
- INTERRUPT_GlobalInterruptEnable();
- int i;
-
- // LED指示
- LED0_SetLow();
-
- // 初始化动作,表明程序运转
- fb_flag=1;
- plan_step=512;
- __delay_ms(1000);
- fb_flag=2;
- plan_step=512;
- // LED指示
- LED0_SetHigh();
- __delay_ms(2000);
- fb_flag=0;
- // 启动转动,同时收集ADC数据
- step_all=0;
- fb_flag=1; // 正转方式
- idx=0;
-
- // 主循环处理
- while (1) {
- // 触发ADC转换,并取得转换结果
- ADCON0bits.GO = 1; //Start conversion
- while (ADCON0bits.GO); //Wait for conversion done
- resultHigh = ADRESH; //Read result
- resultLow = ADRESL; //Read result
- // 合成为16位数据
- result=resultHigh;
- result=result*256 + resultLow;
-
- // 计算平均值,并存储
- avrs[idx]=result/ADC_AVR_CNT;
- idx=(idx+1)%ADC_AVR_CNT;
- if (idx==0) {
- // 数据初始化
- avr_result=0;
-
- // 满指定组数据了,求出平均结果
- for (i = 0; i < ADC_AVR_CNT; i++) {
- avr_result=avr_result+avrs[i];
- }
- if (avr_result > adc_max && step_all < STEPS_CYCLE) {
- adc_max = avr_result;
- }
-
-
- if (step_all >= STEPS_CYCLE && fb_flag>0) {
- step_all=STEPS_CYCLE; // 避免累加溢出
- printf("Complete a lap.Search max.\r\n"); //
- // 超过1圈了,反转找最大值位置
- fb_flag=2;
- plan_step=STEPS_1DU;
- //if (avr_result > adc_max-10 && avr_result < adc_max+10) {
- if (avr_result > adc_max-10) {
- // 找到大值,停止。过指定时间之后,再重新定位最大值 TODO
- printf("Finded max-pointer.\r\n"); //
- LED0_SetLow();
- fb_flag=0;
- plan_step=0;
- }
- } else {
- printf("adc=%d, max=%d, step_all=%d\r\n", avr_result, adc_max, step_all); //
- // 转一圈,找最大值
- plan_step=STEPS_1DU;
- }
- }
- }
- }
定时器1中断处理代码如下:- // 定时器1中断,1ms一次
- void TMR1_DefaultInterruptHandler(void){
- uint8_t next_step=0;
- // add your TMR1 interrupt custom code
- // or set custom function using TMR1_SetInterruptHandler()
- // 交替LED作为指示
- //LATFbits.LATF3 = ~LATFbits.LATF3;
- if (fb_flag>0 && plan_step>0) {
- // 允许转动,并且预定了步进步数的场合,启动转动
- // 每间隔固定时间让步进马达走一步
- timer1_int_cnt++;
- if (timer1_int_cnt==step_period_ms) {
- timer1_int_cnt=0;
- if (fb_flag==1) {
- // 正转场合,取得本次步进数据的数据索引
- stepmotor_pos=(stepmotor_pos+1)%STEP_MAX;
- } else if (fb_flag==2) {
- // 反转场合,取得本次步进数据的数据索引
- stepmotor_pos=(stepmotor_pos+STEP_MAX-1)%STEP_MAX;
- }
- // 取得本次步进用时序数据
- next_step=F_Rotation[stepmotor_pos];
- // 执行一次步进
- LATF = (LATF & 0x0F) | next_step;
- // 预定步进总数减一
- plan_step--;
- // 总步数加1
- step_all++;
- }
- } else {
- timer1_int_cnt=0;
- LATF = LATF & 0x0F;
- }
- }
测试时按照两种模式:1、连接电脑测试,通过串口监测中间处理数据,检查程序逻辑。2、离线测试①在1的测试OK的情况下,把整个装置放置在正常光线下测试。②在正常光线下,在与正常光强最强角度不同的某一个角度上利用强光LED手电筒,设置为最强角度,测试装置是否能停留在这个角度。 经过这三种简单的测试,证明了程序可以使装置转到最佳光强位置。实际应用中,可以利用这种思路动态调整太阳能在充电装置,保证在任意时刻找到最合理的角度完成太阳能到电能的转换。[attach]1949426[/attach][attach]1950038[/attach]
作者: robertesth 时间: 2022-8-17 16:00
有读取温湿度的程序吗
作者: zerorobert 时间: 2022-8-18 17:44
光照传感器了解一下。
作者: kkzz 时间: 2022-9-5 13:10
这个高端了。
作者: xiaoyaozt 时间: 2022-9-5 14:09
如何调整角度?
作者: zerorobert 时间: 2022-9-5 15:09
能够实现跟随吗?
作者: pzsh 时间: 2022-11-8 15:38
类似于机器学习?
欢迎光临 21ic电子技术开发论坛 (https://bbs.21ic.com/)
Powered by Discuz! X3.5