5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 3315|回复: 5
打印 上一主题 下一主题

自制 apm/pixhawk 声纳,有问题,请教

[复制链接]
跳转到指定楼层
楼主
发表于 2018-1-21 11:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
点击查看详情

前段,抄袭国外论坛写了 apm/pixhawk 的 I2C 声纳,
用arduino + SR-04 做的,滤波也做了,但定位效果不理想
(比如:地板飞向茶几,高度能拉起来,但再飞回地板,高度就没降下来)
特把源代码贴出来,请讨论指教




//
//  I2C interface for SR04 sonar
//  [ HC-SR04 5V ] <=> [ Trig(8), Echo(9) ArduinoNano 5V SDA(A4), SCL(A5) ] <=> [Bi-Directional Logic Level Converter 5V 3.3V] <=> [Rixracer/Pixhawk I2C]
//  Mission Planner | Optional Hardware | Sonar = MaxbotixI2C
//

#include <Wire.h>
//#define DEBUG

#define MIN_RANGE 10                          // Based on specs from MB1200 data sheet
#define MAX_RANGE 765                         // Based on specs from MB1200 data sheet
#define ARRAY_SIZE 11                          // size of median and mode sampling arrays. Needs to be an odd number

#define  SLAVE_ADDRESS        0x70
#define  MAX_PACKET_LENGHT    3
#define  DATA_LENGHT          2

const int sonar_Trig = 8;
const int sonar_Echo = 9;

byte command[MAX_PACKET_LENGHT];
byte buffer[DATA_LENGHT];

// For Mode / median filter variables needed to store values
// array to store the raw samples
int rawValues[ARRAY_SIZE];
// array to store the sorted samples
int srtValues[ARRAY_SIZE];
// Index for latest position in array
int idx = 0;

int val = 0;
byte* valPtr;
boolean cmdReady = false;

void setup() {
#ifdef DEBUG   
  Serial.begin(57600);
#endif

  valPtr = (byte*) &val;  
  pinMode(sonar_Trig, OUTPUT);
  pinMode(sonar_Echo, INPUT);
  Wire.begin(SLAVE_ADDRESS);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

      for(int i=0; i < ARRAY_SIZE; i++)       // Set all array value to Zeros
      {
        rawValues = 0;
        srtValues = 0;
      }
      idx = 0;                                // Set index to first place in array  
}

void isort(int *a, int n){
    for (int i = 1; i < n; ++i)
  {
    int j = a;
    int k;
    for (k = i - 1; (k >= 0) && (j < a[k]); k--)
    {
      a[k + 1] = a[k];
    }
    a[k + 1] = j;
  }
}

int median(int *x,int n){
return (x[(n/2)]);
}

//Mode function, returning the modal value (or median value if mode does not exist).
int mode(int *x,int n){

  int i = 0;
  int count = 0;
  int maxCount = 0;
  int mode = 0;
  int bimodal;
  int prevCount = 0;

  while(i<(n-1)){

    prevCount=count;
    count=0;

    while(x==x[i+1]){

      count++;
      i++;
    }

    if(count>prevCount&count>maxCount){
      mode=x;
      maxCount=count;
      bimodal=0;
    }
    if(count==0){
      i++;
    }
    if(count==maxCount){                      //If the dataset has 2 or more modes.
      bimodal=1;
    }
    if(mode==0||bimodal==1){                  //Return the median if there is no mode.
      mode=x[(n/2)];
    }
    return mode;
  }
}

void loop() {
  digitalWrite(13, LOW);  
  digitalWrite(sonar_Trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(sonar_Trig, LOW);
  unsigned int  tmp =pulseIn(sonar_Echo, HIGH)/58;
  if (tmp> MAX_RANGE) tmp=MAX_RANGE;
  if (tmp< MIN_RANGE) tmp=0;

    rawValues[idx] = tmp;
    idx++;
    if (idx>=ARRAY_SIZE)
      idx=0;
    for(int i=0; i < ARRAY_SIZE; i++)         // copy raw data to sorted data array
      srtValues=rawValues;
    isort(srtValues,ARRAY_SIZE);              // sort the sorted data array
    //val = median(srtValues,ARRAY_SIZE);       // find the median value and use it
    val = mode(srtValues,ARRAY_SIZE);
  delay(25);
}

void requestEvent()
{
   if ( cmdReady ) {
    digitalWrite(13, HIGH);

    char* ptr = (char*) &val;
    buffer[1] = *ptr++;
    buffer[0] = *ptr++;
    Wire.write(buffer, 2);     
    cmdReady = false;
   }
}

void receiveEvent(int bytesReceived)
{
  for(int i = 0; i < bytesReceived; i++)
  {
    if( i < MAX_PACKET_LENGHT){
      command = Wire.read();
    } else{
        Wire.read();
      }
  }

  switch(command[0]){
    case 0x51:
      cmdReady = true;
    break;  
  }
#ifdef DEBUG  
  Serial.print("Command: " );
  Serial.println(command[0]);
  Serial.println(val);
  /*
  Serial.print(", ");
  Serial.print(command[1]);
  Serial.print(", ");
  Serial.println(command[2]);
  */
#endif  
}



欢迎继续阅读楼主其他信息

沙发
发表于 2018-1-21 13:58 | 只看该作者
这个和这段代码没关系 这段代码只是将pwm输出转化成I2C信号
3
 楼主| 发表于 2018-1-21 15:06 | 只看该作者
hpuxionghao 发表于 2018-1-21 13:58
这个和这段代码没关系 这段代码只是将pwm输出转化成I2C信号

毕竟做了滤波了呀。
但我也觉得问题主要在 SR-04

4
发表于 2018-12-9 02:16 | 只看该作者
学习了,谢谢分享!!!
5
发表于 2018-12-10 12:59 | 只看该作者
看不懂
6
发表于 2019-1-6 16:05 | 只看该作者
同样用arduino + SR-04做过,用APM刷3.2.1版本测试,在电脑上看测试数字视乎还准,但实飞测试时感觉还没气压计定高稳,不知什么原因?
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /2 下一条

快速回复 返回顶部 返回列表