我有4个SingleTact电容式传感器,每个传感器的i2c地址为0x04。我想找到传感器的平均值,以制作操纵杆。但是我不确定如何为每个传感器分配它自己的地址,因为它们都具有相同的地址,因为它们是相同的传感器。我有一个初始代码,但这只适用于一个传感器,因为它只有一个i2c地址字节。我已经使用在线教程将所有SDA和SCL线连接在一起,并包含了上拉电阻。
#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;
}
}
感谢您的任何建议。
答案 0 :(得分:5)
您应该阅读此设备的手册,here。它在界面描述中说,
多个传感器接口可以连接到单个I2C总线。该 可以配置各个传感器接口的总线地址 通过I2C接口写入所需的地址值(4到127) 通过I2C写操作注册地址0。个人变化 PC和Arduino示例支持传感器I2C地址。
所以你必须
然后每个传感器都会回复您设置的地址。
请注意
由于接口板将始终响应地址0x04,因此 必须考虑为SingleTact保留地址。多重的地方 然后将SingleTact接口连接到同一I2C总线 地址0x04必须被视为无效
所以,即使在这种情况下,RTFM建议也是最重要的建议......
答案 1 :(得分:0)
您也可以使用I2C多路复用器。它们有自己的I2C地址,可以在自己的总线(广播域)上枚举四个传感器,以便可以在它们之间切换。您的编程需要依次明确选择每个传感器并跟踪它正在读取的传感器。切换后,I2C流量只会传递到选定的设备。当您运行额外布线时,这最适用于星型拓扑中的一组传感器。
我会更进一步,并说你甚至可以使用继电器来切换这些进出,或者是OR / NAND门。
答案 2 :(得分:-2)
您需要使用卡尔曼滤镜
#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);
}
}