目前我有一个带磁性拾音器的柴油发动机。我想用Arduino(Uno / Nano)测量发动机转速。
磁性拾音器说明:磁性拾音器安装在齿轮上(最常见的是车辆钟罩内的飞轮),当齿轮转动时,拾音器将为齿轮上的每个齿产生电脉冲。然后由仪器读取这些脉冲,该仪器将其解释为指示正确的RPM或速度。来自磁速传感器的信号,每秒齿数(HZ)与发动机速度成正比。
磁性拾取图像: MP - Self Powered
我试图用二极管整流信号,然后使用带有.1Uf电容的电阻限制电流来滤除噪声,然后通过观察Arduino中断将其连接到Optocopler 4N35和Opto到Arduino中断引脚的输出ping很受周围环境的影响。
此外,我还尝试将磁性拾音器直接连接到“A0”引脚并使用模拟读取并将LED连接到引脚13,以监控来自MP的脉冲。
int sensorPin = A0;
int ledPin = 13;
int sensorValue = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
digitalWrite(ledPin, HIGH);
delay(sensorValue);
digitalWrite(ledPin, LOW);
Serial.println(sensorValue);
Serial.println(" ");
}
使用analogueRead
与LED一起作为拾取产生的脉冲的指示器。 (使用小型电机和小齿轮进行测试以保护Arduino)。
我也尝试使用LM139比较器,但读数没有意义 (例如:60 RPM,1500 RPM,2150 RPM,7150 RPM)。
与LM139一起使用的代码:
// read RPM
volatile int rpmcount = 0;
//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_fan, RISING);
//interrupt cero (0) is on pin two(2).
}
void loop() {
if (millis() - lastmillis == 500) {
/*Update every one second, this will be equal to reading frequency (Hz).*/
detachInterrupt(0); //Disable interrupt when calculating
rpm = rpmcount * 60;
/* Convert frequency to RPM, note: this works for one interruption per full rotation. For two interrupts per full rotation use rpmcount * 30.*/
Serial.print(rpm); // print the rpm value.
Serial.println(" ");
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, rpm_fan, RISING); //enable interrupt
}
}
void rpm_fan() {
/* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}
// Elimelec Lopez - April 25th 2013
使用Arduino连接磁性拾音器以显示RPM的最佳方式或方法是什么?
答案 0 :(得分:0)
你使用analogRead是错误的。此外,analogRead不会让你接近你想要达到的目标。
您对拾音器的要求是明确的0-5v数字信号。您可以通过在光耦合器上使用输入电阻来获得它。我会做一些测量,并在电路板上放置一个微调电阻器+电阻器,可以在系统安装后调整实际值。
一旦你获得了尽可能干净的电信号,就可以使用Arduino上的中断引脚来计算脉冲数。
#define SENSOR_PIN (2) // using define instead of variable for constants save memory.
#define LED_PIN (13)
#define READ_DELAY (100) // in milliseconds.
// we'll get a reading every 100ms, so 8 bits are enough to keep
// track of time. You'd have to widen to unsigned int if you want
// READ_DELAY to exceed 255 ms.
//
typedef delay_type unsigned char;
typedef unsigned int counter_type; // You may want to use
// unsigned long, if you
// experience overflows.
volatile counter_type pulseCount = 0; // volatile is important here
counter_type lastCount = 0;
delay_type lastTime = 0;
// pulse interrupt callback, keep short.
void onSensorPulse()
{
++pulseCount;
// the following may already be too long. Use for debugging only
// digitalWrite() and digitalRead() are notoriously slow.
//
//
// digitalWrite(LED_PIN, !digitalRead(LED_PIN));
//
// using fastest direct port access instead. (for ATMega)
//
if (pulseCount & 1)
PORTB |= (1 << PB5);
else
PORTB &= ~(1 << PB5);
}
void setup()
{
pinMode(SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), onSensorPulse, RISING);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
// control frequency of readings
//
delay_type now = (delay_type)millis();
if (now - lastTime < READ_DELAY)
{
return;
}
lastTime = now;
// get a reading. must disable interrupts while doing so.
// because pulseCount is multi-bytes.
//
noInterrupts();
counter_type curCount = pulseCount;
interrupts();
// get the number of pulses since last reading.
//
counter_type delta = curCount - lastCount;
lastCount = curCount;
// to convert to RPMs, you will need to use this formula:
// note the use of long (UL) to avoid overflows in the
// computation. 60000 = miliseconds per minute.
//
// RPM = delta * 60000UL / (READ_DELAY * TEETH_COUNT);
// send delta to client for now.
//
Serial.println(delta);
}