未知数 发表于 2014-4-18 20:25:11

arduino 测速

使用是码盘测速,不过对于两个轮子PWM赋值区别很大,可是轮子的#include <MsTimer2.h>
#defineValue 1.02101761//计算周长的常量

//volatile int state = HIGH;

int u_left = 2;//定义U型测速端口
int u_right = 3;

int leftCW=4;//连接电机1转向端口到数字接口4
int rightCW=7;//连接电机2转向端口到数字接口7
int leftPWM=5; //连接电机1调速端口到数字接口5   
int rightPWM=6;//连接电机2调速端口到数字接口6

int r_wheel = 0; //记录U型测速模块的次数
int l_wheel = 0;
float r_velocity=0;//速度;
float l_velocity=0;

float velocity(int n)
{
//(n/20)轮子装的圈数,轮子直径是65mm
//速度的计算公式应该为(n/20)×(65×10-1×π)即n*1.02101761
//后面的计算得常数
float vel =Value*(n/20);
return vel;
}
void flash()
{//noInterrupts();
//String s1="";
// String s2="";
int r,l;
r=r_wheel;l=l_wheel;
//noInterrupts();
r_velocity=velocity(r);
l_velocity=velocity(l);
//Serial.print(r_velocity);
// Serial.print("\0");
// itoa (r_wheel,buffer1,10);
//itoa (l_wheel,buffer2,10);
//s1+=r;
//s2+=l;

Serial.print(l_velocity);
   Serial.print("cm/s(L)");
Serial.print(" ");
// Serial.print(l_velocity);
// Serial.print("\0");
Serial.print(r_velocity);
   Serial.println("cm/s(R)");
r_wheel = 0;
l_wheel = 0;
//interrupts();
}


void setup ()
{
Serial.begin(9600);

attachInterrupt(0,RCount, FALLING);
attachInterrupt(1,LCount, FALLING);

pinMode(leftCW,OUTPUT);
pinMode(leftPWM,OUTPUT);
pinMode(rightCW,OUTPUT);
pinMode(rightPWM,OUTPUT);

MsTimer2::set(1000, flash);      // 中断设置函数,每 1s 进入一次中断
MsTimer2::start();

}

void loop()
{
digitalWrite( leftPWM,10);//电机1全速前进
digitalWrite(rightPWM,200);//电机2全速前进
digitalWrite(leftCW,HIGH);//电机1正转
digitalWrite(rightCW,HIGH);//电机2正转

while (1)
{
//   digitalWrite(13, state);
}

}
void LCount()
{
l_wheel++;
// state=!state;

}
void RCount()
{
r_wheel++;
}


速度相差不大,通过串口测试了一下,结果如图,各位大神看一下,有没有问题啊!

Super169 发表于 2014-4-18 22:54:46

本帖最后由 Super169 于 2014-4-18 22:59 编辑

少少意見, 由於我沒用過 <MsTimer2.h>, 有些地方想先確認.

MsTimer2::set(1000, flash);

是指每秒執行一次, 而非在第一次執行完一秒後執行, 對嗎?

如果是這樣的話, 重設 l_wheel 及 r_wheel 應盡快進行, 盡可能放最前的位置.
因為 flash 程序執行亦需要時間 (特別是 Serial.print 的部份), 為免影響計算, 在讀取完 r_wheel 及 l_wheel 後即時重設會比較好.

另一個問題是 Arduino 的 interrupt 設計, 當其中一個 interrup 執行中, 另一個 interrupt 好像會被 ignore 的.
現在左右相差很大, 右邊最少有 25% interrupt 遺失了. 假定左邊沒遺失, 右邊比左邊少 25%, 如左邊亦有遺失的話, 實際遺失比例更高.

此外, 亦不太明白你的速度計算, 請問 是否一圈就有 20 格?
如果是的話, 速度不是(n/20) * (65 * 3.1416) 嗎?應該是 n * 1.0210

未知数 发表于 2014-4-19 00:17:32

谢谢啊,看你的回复,真心受教了。赋值确实是这样,我处理的不太好。那个速度计算,我在备注这样写的,因为代码有几次改动,所以改着改着就错了。还想请教一下,关于中断ignore,这个改怎么解决呢?或者有其他方法计算码盘的转值。

未知数 发表于 2014-4-19 00:19:53

Super169 发表于 2014-4-18 22:54 static/image/common/back.gif
少少意見, 由於我沒用過 , 有些地方想先確認.

MsTimer2::set(1000, flash);


谢谢啊,看你的回复,真心受教了。赋值确实是这样,我处理的不太好。那个速度计算,我在备注这样写的,因为代码有几次改动,所以改着改着就错了。还想请教一下,关于中断ignore,这个改怎么解决呢?或者有其他方法计算码盘的转值。

wangweihe68 发表于 2014-4-19 01:30:58

未知数 发表于 2014-4-19 00:17 static/image/common/back.gif
谢谢啊,看你的回复,真心受教了。赋值确实是这样,我处理的不太好。那个速度计算,我在备注这样写的,因为 ...

刚开始接触arduino,很多8051有单独的计数器管脚,配置好触发方式就行,不占用系统中断,这个问题就很好解决了,不知道arduino有吗?avr貌似也有

Super169 发表于 2014-4-19 02:39:35

未知数 发表于 2014-4-19 00:19 static/image/common/back.gif
谢谢啊,看你的回复,真心受教了。赋值确实是这样,我处理的不太好。那个速度计算,我在备注这样写的,因 ...

同時有頻密的多個 interrupt, 我也不知 Arduino 是否有解決方法.

樓據網上資料:

Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be ignored (turned off) until the current one is finished. as delay() and millis() both rely on interrupts, they will not work while an ISR is running. delayMicroseconds(), which does not rely on interrupts, will work as expected.

如果左右同時 觸發, 有可能當中一個會被 ignore.而且, LCount 及 RCount 也算是 short 了, 但 flash 實在有點長.我不太肯定 MsTimer2 是否也是經 interrupt 觸發, 如果是的話, 因為執行 flash 而導致 lcount/rcount 失效的機會更大.

如果是 flash 引致就好辦了, 只要把 flash 改成不再由 interrupt 觸發就可以了, 例如放在 loop() 內, 再自行計算兩次讀取計數值的時間差去推算速度.雖然多了一點計算, 但相信不會是問題.

但如果是因為左右同時觸發, 至導致當中一個失效, 就比較難解決了.

如果有個計數器的模塊自動計數, 無需靠 interrupt 計數, 在 Arduino 中向它發出要求, 回傳及重設數值會比較安全.

hmjack2008 发表于 2014-4-19 03:38:09

16位的T/C 可以实现外部事件计数器
Arduino Frequency Counter Library :
http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/

未知数 发表于 2014-4-19 09:15:58

Super169 发表于 2014-4-19 02:39 static/image/common/back.gif
同時有頻密的多個 interrupt, 我也不知 Arduino 是否有解決方法.

樓據網上資料:


/*
* SimpleTimer.cpp
*
* SimpleTimer - A timer library for Arduino.
* Author: [email protected]
* Copyright (c) 2010 OTTOTECNICA Italy
*
* This library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software
* Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser
* General Public License along with this library; if not,
* write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/


#include "SimpleTimer.h"


SimpleTimer::SimpleTimer() {
    unsigned long current_millis = millis();

    for (int i = 0; i < MAX_TIMERS; i++) {
      enabled = false;
      callbacks = 0;                   // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer
      prev_millis = current_millis;
      numRuns = 0;
    }

    numTimers = 0;
}


void SimpleTimer::run() {
    int i;
    unsigned long current_millis;

    // get current time
    current_millis = millis();

    for (i = 0; i < MAX_TIMERS; i++) {

      toBeCalled = DEFCALL_DONTRUN;

      // no callback == no timer, i.e. jump over empty slots
      if (callbacks) {

            // is it time to process this timer ?
            if (current_millis - prev_millis >= delays) {

                // update time
                prev_millis = current_millis;

                // check if the timer callback has to be executed
                if (enabled) {

                  // "run forever" timers must always be executed
                  if (maxNumRuns == RUN_FOREVER) {
                        toBeCalled = DEFCALL_RUNONLY;
                  }
                  // other timers get executed the specified number of times
                  else if (numRuns < maxNumRuns) {
                        toBeCalled = DEFCALL_RUNONLY;
                        numRuns++;

                        // after the last run, delete the timer
                        if (numRuns >= maxNumRuns) {
                            toBeCalled = DEFCALL_RUNANDDEL;
                        }
                  }
                }
            }
      }
    }

    for (i = 0; i < MAX_TIMERS; i++) {
      switch(toBeCalled) {
            case DEFCALL_DONTRUN:
                break;

            case DEFCALL_RUNONLY:
                (*callbacks)();
                break;

            case DEFCALL_RUNANDDEL:
                (*callbacks)();
                deleteTimer(i);
                break;
      }
    }
}


// find the first available slot
// return -1 if none found
int SimpleTimer::findFirstFreeSlot() {
    int i;

    // all slots are used
    if (numTimers >= MAX_TIMERS) {
      return -1;
    }

    // return the first slot with no callback (i.e. free)
    for (i = 0; i < MAX_TIMERS; i++) {
      if (callbacks == 0) {
            return i;
      }
    }

    // we should never reach this point...
    return -1;
}


int SimpleTimer::setTimer(long d, timer_callback f, int n) {
    int freeTimer;

    freeTimer = findFirstFreeSlot();
    if (freeTimer < 0) {
      return -1;
    }

    delays = d;
    callbacks = f;
    maxNumRuns = n;
    enabled = true;
    prev_millis = millis();

    numTimers++;

    return freeTimer;
}


int SimpleTimer::setInterval(long d, timer_callback f) {
    return setTimer(d, f, RUN_FOREVER);
}


int SimpleTimer::setTimeout(long d, timer_callback f) {
    return setTimer(d, f, RUN_ONCE);
}


void SimpleTimer::deleteTimer(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return;
    }

    // nothing to delete if no timers are in use
    if (numTimers == 0) {
      return;
    }

    callbacks = 0;
    enabled = false;
    delays = 0;
    numRuns = 0;

    // update number of timers
    numTimers--;
}


// function contributed by [email protected]
void SimpleTimer::restartTimer(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return;
    }

    prev_millis = millis();
}


boolean SimpleTimer::isEnabled(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return false;
    }

    return enabled;
}


void SimpleTimer::enable(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return;
    }

    enabled = true;
}


void SimpleTimer::disable(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return;
    }

    enabled = false;
}


void SimpleTimer::toggle(int numTimer) {
    if (numTimer >= MAX_TIMERS) {
      return;
    }

    enabled = !enabled;
}


int SimpleTimer::getNumTimers() {
    return numTimers;
}这个是MsTimer2的原代码,应该没有用到过中断。arduino本身不含定时计数器中断,上网找过也没有看到什么计数库。所以用的是中断。现在也没什么好办法了。

未知数 发表于 2014-4-19 09:22:38

hmjack2008 发表于 2014-4-19 03:38 static/image/common/back.gif
16位的T/C 可以实现外部事件计数器
Arduino Frequency Counter Library :
http://interface.khm.de/index ...

这个默认频率输入端口是5,能不能设置成其他的?我没用过这个库,看介绍还是大概还不太了解,能给指教一下?

未知数 发表于 2014-4-19 10:03:05

wangweihe68 发表于 2014-4-19 01:30 static/image/common/back.gif
刚开始接触arduino,很多8051有单独的计数器管脚,配置好触发方式就行,不占用系统中断,这个问题就很好解 ...

没有吧,arduino就两个外部中断。

未知数 发表于 2014-4-19 10:05:17

未知数 发表于 2014-4-19 09:15 static/image/common/back.gif
这个是MsTimer2的原代码,应该没有用到过中断。arduino本身不含定时计数器中断,上网找过也没有看到什么计 ...

把你说的另外两个问题改了,测试一下,左轮速度比右轮还要快,PWM设置左轮是10,右轮是200,误差应该还是很大。

eddiewwm 发表于 2014-4-19 11:33:26

兩個電機的 PWM的推動值區別真的很大,若PWM的推動情況沒問題的話,那麼問題應在電機上了,應檢查一下!
//
digitalWrite( leftPWM,10);//电机1全速前进
digitalWrite(rightPWM,200);//电机2全速前进
//

未知数 发表于 2014-4-19 12:51:38

eddiewwm 发表于 2014-4-19 11:33 static/image/common/back.gif
兩個電機的 PWM的推動值區別真的很大,若PWM的推動情況沒問題的話,那麼問題應在電機上了,應檢查一下!
/ ...

犯了一个常识性错误,PWM端口应该用analogWrite

Super169 发表于 2014-4-19 14:00:13

eddiewwm 发表于 2014-4-19 11:33 static/image/common/back.gif
兩個電機的 PWM的推動值區別真的很大,若PWM的推動情況沒問題的話,那麼問題應在電機上了,應檢查一下!
/ ...

oh.. 沒留意到有這麼大的分別, 一直以為是等速. 而且是用了 digitalWrite....

张常青 发表于 2014-11-18 13:53:27

敢问你是用什么方法来消除干扰的
页: [1] 2
查看完整版本: arduino 测速