使用 ATmega88

如何解决使用 ATmega88

我提供了以下 C 代码来测试 60V DC motor 比率为 16:1 的 gear box 和增量编码器,以查看代码是否通过读取脉冲信号作为 μcontroller 的反馈来计算速度编码器。微控制器是 ATmega88A-UA。编码器 RE56-3-1000 TI 表示 1000 ppr。 特殊场合的直流电机需要以 3-4 转/分的速度运行以完成特定任务。 在较低的速度下,例如低于 5V,电机的启动电压为 1.8V,软件似乎计算出不正确的速度值。 低速时模式为TCCR1B == 0x02,速度值相对较高,255-1071,2V-5V,频率751Hz -3.6kHz。

当模式切换到 TCCR1B == 0x01 时,计算/观察到的速度值(通过调试)范围为 471 - 1140 at 8V - 20V,频率为 6.2kHz - 17.4kHz。

我还观察到模式 TCCR1B 在 0x01 和 0x02 之间不断切换,特别是在 2kHz 和 4kHz 之间的频率。

有没有人了解不正确的值计算可能会带来什么麻烦。是否存在某种时序问题?使用的速度变量是一个无符号整数。我需要你的帮助。 事情很可能没有得到很好的解释。我会尽力给出正确的答案。产品链接包含在说明中。 任何形式的帮助/建议将不胜感激。谢谢

#include "iom88.h"
#include "main.h"

 unsigned int Test_Speed_low;           //For testing only!!
 unsigned int Test_Speed_1;             //For testing only!!
 unsigned int Test_Speed_2;             //For testing only!!
 unsigned int Test_Value_Timer_2;       //For testing only!!

int main(void)
{  
  // 1 rpm    ->    1000 / 60 = 16,6 Pulse/s  -> 1000 / 16,6 = 60,25 ms/Pulse
  // 10 rpm   ->   10000 / 60 = 166  Pulse/s  -> 1000 / 166  = 6,025 ms/Pulse 
  // 120 rpm  ->  120000 / 60 = 2000 Pulse/s  -> 1000 / 2000 = 0,5   ms/Pulse
  // 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 1000 / 33333 = 0,03 ms/Pulse
  // 8 Mhz -> 0,125 us / Takt
  // Timer1 CLK/8 -> 1 us / Timer cycle -> 65535 * 1 us = 62 ms -> ~ 1 rpm
  // If pulse is faster than 0.5 ms then measure 10 im pulses with
  // Timer1 CLK/1 -> 0,125 us / Timer cycle -> 65535 * 0,125 us = 8192 us = 8 ms 
  // 120 rpm  ->  120000 / 60 = 2000 Pulse/s  -> 10 Pulse = 5 ms -> 5000 us / 0,125 us = 40000 Timerticks
  // 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 10 Pulse = 0,3 ms -> 300 us / 0,125 us = 2400 Timerticks
    
  PORTB = 0x00;           // No Pullups
  DDRB = 0x03;            // PORTB_Bit0 = 1k3,Bit1 = 0R

  PORTC = 0; 
  DDRC = 0x1F;            // Out_0-4 Outputs 47k,22k,11k,5k6,2k7

  PORTD = 0x20;           // Pull-Up T1 (Bit5)
  DDRD = 0x00;                                
  
  ACSR = 0x80;            // Disable Analog Comparator 
  DIDR1 = 0x03;           // Disable input register on AIN0/AIN1
  ADCSRA = 0xC7;          // Clock / 128 slower is not possible,no INT  
  ADMUX = 0xC5;           // Int 1,1V Ref,ADC5
  DIDR0 = 0x20;           // Disable input register on ADC5
  
  TCCR0A = 0x02;          // T0 CRC mode 
  TCCR0B = 0x06;          // T0 External clock source on falling edge 
  OCR0A = 1;              // CRC int after 1 clocktick
  TIMSK0 = 0x02;          // Timer 0 Compare match A int

  TCCR1A = 0x00;          // T1 normal mode 
  TCCR1B = 0x02;          // clk/8 source on T1
  TIMSK1 = 0x01;          // Timer 1 Overflow int  
  Value_TCCR1B = TCCR1B;
  Value_Timer1 = 60000;
  
  Min_Timer1 = 60000;
  Max_Timer1 = 0; 
  Counter_Timer1 = 0;
  
  Test_Speed_1 = 0;       //For testing only!!
  Test_Speed_2 = 0;       //For testing only!!
  Test_Speed_low = 0;       //For testing only!!
  
  EAL = 1;   
    
  while(1)
  { 
    if (TCCR1B == 0x02) {
      if (Value_Timer1 <= 500) {   // < 0,5 ms / Pulse
        OCR0A = 8;                 // CRC int after 8 clocktick  
        TCNT0 = 0;                // Reset timer 0 value
        TCCR1B = 0;               // stop T1
        TCNT1 = 0;                // Reset timer 1 value
        TCCR1B = 1;               // clk/1 source on T1
        Value_TCCR1B = TCCR1B;
      }  
    } else {    
      if (Value_Timer1 > 40000) {  // > 0,5 ms / 10 Pulse     //Slow Mode
        OCR0A = 1;                // CRC int after 1 clocktick  
        TCNT0 = 0;                // Reset timer 0 value
        TCCR1B = 0;               // stop T1
        TCNT1 = 0x1FF;
        TCCR1B = 2;               // clk/8 source on T1
        Value_TCCR1B = TCCR1B;
      }  
    } 
    
    if (Counter_Timer1 > 2) {
     if (Value_Timer1 < Min_Timer1) {
        Min_Timer1 = Value_Timer1;
      }
      if (Value_Timer1 > Max_Timer1) {
        Max_Timer1 = Value_Timer1;
      }
      if (Counter_Timer1 > 1000) { 
        Counter_Timer1 = 0;
        Min_Timer1 = 60000;
        Max_Timer1 = 0;
      }
    }     

    if (TCCR1B == 0x02) 
    {                      
      Test_Value_Timer_2 = (Value_Timer1/10);         //For testing
      Speed = (60000/Test_Value_Timer_2); // 0,1 RPM,at 60000 uS -> 1 RPM
      Test_Speed_low = Speed;
    } 
    else 
    { 
      if (Value_Timer1 > 10000)
      {
        Test_Value_Timer_2 = (Value_Timer1/100);      //For Testing
        Speed = (48000/Test_Value_Timer_2); // 1 RPM,at 5000 uS -> 120 RPM
        Test_Speed_1 = Speed;           //For testing only!!
      } 
      else 
      { 
        Test_Value_Timer_2 = (Value_Timer1/10);         //For testing
        Speed = (48000/Test_Value_Timer_2);  // 1 RPM,at 5000 uS -> 120 RPM 
        Speed *= 10;
        Test_Speed_2 = Speed;       //For testing only!!
      }  
    } 
  }
}

#pragma vector=INT0_vect

__interrupt void INT0_int(void)    
{
}

#pragma vector=INT1_vect

__interrupt void INT1_int(void)    
{
}

#pragma vector=TIMER0_COMPA_vect

__interrupt void TIMER0_COMPA_int(void) 
{
  TCCR1B = 0;                   // Timer1 Stop
  Value_Timer1 = TCNT1;
  TCNT1 = 0;                    // Reset timer 1 value
  TCCR1B = Value_TCCR1B;  
  Counter_Timer1++;   
  Counter_Int = 1;
}

#pragma vector=TIMER1_OVF_vect

__interrupt void TIMER1_OVF_int(void) 
{
 if (Timer1_OVF == 2)           // Speed < 1,0 RPM
 {   
   Speed = 0;
 } 
 else 
 {
    Timer1_OVF++;
 }
}

解决方法

我会说代码存在一些问题,即使不是很清楚代码如何读取编码器。

首先,当您知道 TCNT1 的值(大约为 0)时,只能在中断中处理 TCNT1。否则,您会覆盖计数器并导致数据丢失。

其次,您观察到 TCCR1B 的切换速度非常快,但本不该如此。这种切换机制可能需要一些延迟,否则当电机速度接近阈值时,事情就会变得不稳定。

第三,也许不相关,但是:Timer1_OVF 什么时候清零?

最后,在我看来,所有代码都过于复杂,编写和修补没有明确的意图。例如,变量 Value_TCCR1B 似乎没有用...

如果可能,我会尝试重新开始:以几种不同的速度运行电机,并使用 TCCR1B 的两个可能值测量它们;然后仔细查看数据并尝试重新制定算法。

只是一个想法;祝你好运!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-