2017-02-09 1 views
1

Ich habe 4 SingleTact-kapazitive Sensoren mit der i2c-Adresse 0x04. Ich möchte den Durchschnittswert der Sensoren finden, um einen Joystick zu machen. Ich bin mir jedoch nicht sicher, wie man jedem Sensor seine eigene Adresse zuweist, da sie alle die gleiche Adresse haben wie der gleiche Sensor. Ich habe einen Anfangscode, aber das funktioniert nur mit einem einzigen Sensor, da es nur ein einziges i2c-Adressbyte hat. Ich habe alle SDA- und SCL-Leitungen zusammen mittels Online-Tutorials verdrahtet und Pull-Up-Widerstände eingebaut.Lesen von Werten von i2c-Sensoren mit der gleichen Adresse

#include <Wire.h> 
#define initializetime 4 
byte serialToPCBuffer[77]; 
byte serialToPCBufferIndex = 0; 

int data[4]; 
int databuffer[4][initializetime] = {0,0,0,0,0,0,0,0,0,0,0,0}; 
int base[4] = {0,0,0,0}; 
int ArduinoToPCBuffer[4] = {1000,2000,3000,4000}; 
byte outgoingI2CBuffer[32]; 
unsigned long timeStamp_; 

void setup() { 
    int i; 
    Wire.begin(); 
    //TWBR = 12; 
    Serial.begin(57600); 
    Serial.flush(); 
    initializeSensors(); 

    while (!Serial) { 
    ; // wait for serial port to connect. Needed for native USB port only 
    } 
    Serial.println("PPS UK: SingleTact sensor value in PSI. \n(resembles PC executable display)"); 
    Serial.println("Refer manual for any other calculation."); 
    Serial.println("----------------------------------------"); 
}  

void loop(){ 
    byte i2cAddress = 0x04; // Slave address (SingleTact), default 0x04 
    int data = readDataFromSensor(i2cAddress); 
    Serial.print("I2C Sensor Data:"); 
    Serial.print(data);  
    Serial.print("\n"); 
    delay(100); // Change this if you are getting values too quickly 
} 

int readDataFromSensor(int address) 
{ 
    byte i = 0; 
    byte i2cPacketLength = 6; 
    byte outgoingI2CBuffer[3]; 
    byte incomingI2CBuffer[6]; 

    outgoingI2CBuffer[0] = 0x01; 
    outgoingI2CBuffer[1] = 128; 
    outgoingI2CBuffer[2] = i2cPacketLength; 

    Wire.beginTransmission(address); 
    Wire.write(outgoingI2CBuffer,3); 
    byte error = Wire.endTransmission(); 
    if (error != 0) return -1; 
    Wire.requestFrom(address,i2cPacketLength); 

    int incomeCount =0; 
    while(incomeCount < i2cPacketLength) 
    { 
    if(Wire.available()) 
    { 
    incomingI2CBuffer[incomeCount] = Wire.read(); 
    incomeCount++; 
    } 
    else 
    { 
    delay(1); 
    } 
    } 
    if(serialToPCBuffer[4] == 0x00 && serialToPCBuffer[5] == 0xFE) 
    { 
    serialToPCBuffer[5] = 0xFF; 
    } 

    int datafromi2c = serialToPCBuffer[4]*256+serialToPCBuffer[5]-base[address-5]; 

    if(datafromi2c<21) 
    datafromi2c = 0; 

    return datafromi2c; 
} 

void initializeSensors() 
{ 
    for(int k = 0;k<4;k++) 
    { 
    databuffer[k][0] = readDataFromSensor(k+5); 
    delay(10); 
    databuffer[k][1] = readDataFromSensor(k+5); 
    delay(10); 
    databuffer[k][2] = readDataFromSensor(k+5); 
    delay(10); 
    databuffer[k][3] = readDataFromSensor(k+5); 
    delay(10); 
    base[k] = (databuffer[k][0] + databuffer[k][1] + databuffer[k][2] +  databuffer[k][3])/3; 
    } 
} 

Danke für jeden Hinweis.

+0

sehen : [Ändern der i2c-Adresse] (http://electronics.stackexchange.com/questions/98054/changing-i2c-address) –

Antwort

3

Sie sollten das Handbuch des Gerätes, zur Verfügung here lesen. In der Schnittstellenbeschreibung heißt es:

Mehrere Sensorschnittstellen können an einen einzigen I2C-Bus angeschlossen werden. Die Busadresse der einzelnen Sensorschnittstellen kann durch Konfigurieren des gewünschten Adresswerts (4 bis 127) über die I2C-Schnittstelle zu Registeradresse 0 mit einem I2C-Schreibvorgang konfiguriert werden. Änderung der einzelnen Sensor I2C Adressen wird vom PC und Arduino Beispiel unterstützt.

So haben Sie gerade zu

  1. dem ersten Sensor
  2. eine Adresse schreiben Stecker (zB 0x41) an das Register 0 dieses Geräts
  3. den Sensor
  4. wiederholt 1- ziehen 2-3 für alle Sensoren mit unterschiedlichen Adressen

Dann wird jeder Sensor rep an die Adresse, die Sie festgelegt haben.

Bitte beachten Sie, dass

Da die Schnittstellenkarte wird immer reagieren 0x04 Adresse dann diese -Adresse muss für SingleTact reserviert betrachtet werden. Wenn mehrere SingleTact Schnittstellen zum gleichen I2C-Bus zu verbinden ist dann Adresse 0x04 muss die wichtigsten

Also, auch in diesem Fall der RTFM Rat ist, als ungültig betrachtet werden ...

0

Sie benötigen die Kalman-Filter

#include "Wire.h"      // i2c library 
    #include "BMP085.h"     // bmp085 library, download from url link (1) 
    #include "Tone.h"      // tone library, download from url link (3) 
    #include "stdlib.h"     // we need that to use dtostrf() and convert float to string 
    #include "stdarg.h" 

    #define UART_SPEED 9600 
    short SPEAKER_PIN1 = 11;    // Speaker output - 
    short SPEAKER_PIN2 = 12;    // Speaker output + 
    short LED_PIN = 13; 

    Tone speaker1, speaker2; 
    BMP085 bmp085 = BMP085();   // BMP085 sensor 

    const float SEA_LEVEL_PRESSURE = 101325; // Pressure at sea level (Pa) 
    const float KF_VAR_MEASUREMENT = 0.1;  // Variance of pressure measurement noise. 
    const float KF_VAR_ACCEL = 0.75;    // Variance of pressure acceleration noise input. 

    float CLIMB_TONE2_MULT; 
    float SINK_TONE2_MULT; 

    float kf_x_abs, 
      kf_x_vel, 
      kf_p_abs_abs, 
      kf_p_abs_vel, 
      kf_p_vel_vel, 
      kf_var_accel; 

    #define VARIOS_LEN 5 
    int varios[VARIOS_LEN]; 
    int varios_pos = 0, varios_sum = 0; 

    void p(char *fmt, ...){ 
     char tmp[128]; // resulting string limited to 128 chars 
     va_list args; 
     va_start (args, fmt); 
     vsnprintf(tmp, 128, fmt, args); 
     va_end (args); 
     Serial.print(tmp); 
    } 

    void kf_reset(float abs_value, float vel_value) { 
     kf_x_abs = abs_value; 
     kf_x_vel = vel_value; 
     kf_p_abs_abs = 1000000000; 
     kf_p_abs_vel = 0; 
     kf_p_vel_vel = KF_VAR_ACCEL; 
     kf_var_accel = KF_VAR_ACCEL; 

     varios_sum = 0; 
     for (int i = 0; i < VARIOS_LEN; i++) varios[i] = 0; 
     varios_pos = 0; 
    } 

    void setup() { 
     Serial.begin(UART_SPEED);   // set up arduino serial port 
     Wire.begin();      // lets init i2c protocol 
     speaker1.begin(SPEAKER_PIN1);  // piezo speaker output - 
     speaker2.begin(SPEAKER_PIN2);  // piezo speaker output + 
     digitalWrite(SPEAKER_PIN2, LOW); 

     bmp085.init(MODE_ULTRA_HIGHRES, SEA_LEVEL_PRESSURE, false); 

     kf_reset(SEA_LEVEL_PRESSURE, 0); 

     CLIMB_TONE2_MULT = pow(2, 9/12); 
     SINK_TONE2_MULT = pow(2, 1/12); 

     welcome();  //everything is ready, play "welcome" sound 
    } 

    void welcome() { 
     speaker1.play(300, 50);  // (note, duration) 
     delay(100); 
     speaker2.play(300, 50);  // (note, duration) 
     delay(100); 
     Serial.println("Vario is ready"); 
    } 

    float pressure2altitude(float pressure) { 
     return (float)44330 * (1 - pow(((float)(pressure)/SEA_LEVEL_PRESSURE), 0.190295)); 
    } 

    float last_time = 0; 
    void update_pressure() { 
     long pressure; 
     bmp085.calcTruePressure(&pressure); 

     float time = millis(); 
     float dt = (time - last_time)/1000; 
     last_time = time; 

     /* Kalman Filter code */ 
     kf_x_abs += kf_x_vel * dt; 

     kf_p_abs_abs += (float)2 * dt * kf_p_abs_vel + dt * dt * kf_p_vel_vel + kf_var_accel * dt * dt * dt * dt/(float)4; 
     kf_p_abs_vel +=          dt * kf_p_vel_vel + kf_var_accel * dt * dt * dt/(float)2; 
     kf_p_vel_vel +=               + kf_var_accel * dt * dt; 

     // Update state covariance. The last term mixes in acceleration noise. 
     float y = pressure - kf_x_abs;        // Innovation. 
     float s_inv = 1.0/(kf_p_abs_abs + KF_VAR_MEASUREMENT); // Innovation precision. 
     float k_abs = kf_p_abs_abs * s_inv;       // Kalman gain 
     float k_vel = kf_p_abs_vel * s_inv; 

     // Update state estimate. 
     kf_x_abs += k_abs * y; 
     kf_x_vel += k_vel * y; 

     // Update state covariance. 
     kf_p_vel_vel -= kf_p_abs_vel * k_vel; 
     kf_p_abs_vel -= kf_p_abs_vel * k_abs; 
     kf_p_abs_abs -= kf_p_abs_abs * k_abs; 
    } 

    int avg_vario() { 
     float altitude = pressure2altitude(kf_x_abs); 
     int vario = (int)((altitude - pressure2altitude(kf_x_abs - kf_x_vel)) * 100); 

     varios_sum += vario; 
     varios_sum -= varios[varios_pos]; 
     varios[varios_pos] = vario; 

     if (++varios_pos == VARIOS_LEN) varios_pos = 0; 
     return varios_sum/VARIOS_LEN; 
    } 


    int CLIMB_RATE_START = 25, 
     SINK_RATE_START = -80; 

    int loop_id = 0; 
    unsigned long next_signal_time = 0; 
    void loop() { 
     update_pressure(); 
     int vario = avg_vario(); 

     unsigned long time = millis(); 
     if (time >= next_signal_time) { 
      if (vario > CLIMB_RATE_START) { 
       long beep_period = 350 - vario/2; 
       if (beep_period < 20) beep_period = 20; 

       int silence_period = beep_period/16; 
       int tone = 1300 + vario; 
       if (tone > 2300) tone = 2300; 

       next_signal_time = time + beep_period + silence_period; 
       speaker1.play(tone, beep_period); 

       Serial.print("CLIMB beep:"); 
       Serial.print(beep_period); 
       Serial.print(" silence:"); 
       Serial.print(silence_period); 
       Serial.print(" vario: "); 
       Serial.println(vario); 
      } else if (vario < SINK_RATE_START) { 
    //   int beep_period = 350 * 50/(-vario); 
    //   int silence_period = beep_period/5; 
       int beep_period = 350 + vario/2; 
       if (beep_period < 20) beep_period = 20; 
       int silence_period = beep_period/16; 
       int tone = 1000 + vario; 
       if (tone < 300) tone = 300; 

       next_signal_time = time + beep_period + silence_period; 
       speaker1.play(tone, beep_period);  // (note, duration) 

       Serial.print("SINK beep:"); 
       Serial.print(beep_period); 
       Serial.print(" silence:"); 
       Serial.print(silence_period); 
       Serial.print(" vario: "); 
       Serial.println(vario); 
      } 
     } 

     loop_id++; 
     if ((loop_id % 10) == 0) { 
      Serial.print("vario: "); 
      Serial.println(vario); 
     } 

     if ((loop_id % 10) == 0) { 
      digitalWrite(LED_PIN, LOW); 
     } 
     if ((loop_id % 10) == 5) { 
      digitalWrite(LED_PIN, HIGH); 
     } 
    } 
+2

Entschuldigung, aber wie antwortet diese Antwort auf die OP-Frage? er fragt, wie man von 4 Sensoren mit der gleichen Adresse liest, nicht wie man die Daten von einem Sensor liest. – frarugi87

Verwandte Themen