Здравствуйте. Понадобилось мне сделать плату для спидометра, потому как часто приносят их в ремонт, а оживить не всегда представляется возможным, поэтому решил сделать аналог на ардуино. Спидометр представляет собой стрелочный логометр с двумя катушками.
Нашел код, который им управляет, успешно протестировал, работает, под мои задачи полностью подходит.
Дальше задача измерить частоту которая приходит с датчика скорости. Нашел код который меряет время между прерываниями при изменении уровня на ножке Д2. В целом код работает корректно, все меряет точно, мне нужно от 0 до 200гц. и на стрелку и порт выдает ± точное значение частоты, но!
Вот но меня бесит неимоверно. Иногда проскакивают какие-то непонятные значения и стрелка дергается, а в порту появляются значение в 2 раза превышающие реальную частоты или около того. Меня такой режим работы не устраивает, потому как дергается стрелка весьма заметно, но что поделать и как победить это я так и не нашел.
вот здесь человек описывает похожий глюк, но ему никто не ответил.
Помогите пожалуйста решить проблему
//this is the maximum resolution of the PWM output.
const int maxAnalogRes = 255;
const int aircore1SinDirPin1 = 3; //sin+ these two control the polarity to the “sine” coil
const int aircore1SinDirPin2 = 5; //sin-
const int aircore1CosDirPin1 = 11; //cos+ these two control the polarity to the “cosine” coil
const int aircore1CosDirPin2 = 6; //cos-
volatile unsigned long duration = 0;
volatile unsigned long lastMicros = 0;
volatile unsigned long frequency1;
volatile unsigned long frequency2;
volatile int frequency;
void setup()
{
Serial.begin(115200); // Инициализация порта, скорость 115200 бод [1, 3]
TCCR2B = TCCR2B & 0b11111000 | 0x01;
TCCR0B = TCCR0B & 0b11111000 | 0x01;
//Set the pins to OUTPUT
pinMode(aircore1SinDirPin1, OUTPUT);
pinMode(aircore1SinDirPin2, OUTPUT);
pinMode(aircore1CosDirPin1, OUTPUT);
pinMode(aircore1CosDirPin2, OUTPUT);
//прерывание по изменению сигнала на выводе 2
attachInterrupt(digitalPinToInterrupt(2), pulseCounter, RISING);
pinMode(2, INPUT_PULLUP);
}
void loop()
{
int val;
Serial.println(frequency);
if (duration > 0) {
val = map(frequency, 0, 200, -140, 300);
setMeterPosition(aircore1SinDirPin1, aircore1SinDirPin2, aircore1CosDirPin1, aircore1CosDirPin2, val);
}
delay(5000);
}
void pulseCounter() {
unsigned long currentMicros = millis();
duration = currentMicros - lastMicros;
frequency = 62500 / duration;
//frequency2 = frequency1*2;
//if (frequency >= frequency2 ) {
// frequency = frequency/2;
//}
lastMicros = currentMicros;
//frequency1 = frequency;
}
//Код движения стелки логометра. работает идеально.
// setMeterPosition() - put it at the angle in radians
void setMeterPosition( int sinDirPin1, int sinDirPin2, int cosDirPin1, int cosDirPin2, float pos){
pos=pos/100;
// Calculate the voltage on the PWM pins based on the angle we want
float sinCoilValue = maxAnalogRessin(pos);
float cosCoilValue = maxAnalogRescos(pos);
int sinn=0;
int coss=0;
if (sinCoilValue<=0) {
sinn = 1;
}
if (cosCoilValue<=0) {
coss = 1;}
// take the absolute value because analogWrite doesn’t take negatives
sinCoilValue = abs(sinCoilValue);
cosCoilValue = abs(cosCoilValue);
// change the polarity of the coil depending on the sign of the voltage level
if (sinn==1) {
analogWrite(sinDirPin1, 0); //Change to LOW if using relays
analogWrite(sinDirPin2, sinCoilValue); //comment this line out if using relays
} else {
analogWrite(sinDirPin1, sinCoilValue); //Change to HIGH if using relays
analogWrite(sinDirPin2, 0); //comment this line out if using relays
}
if (coss==1) {
analogWrite(cosDirPin1, 0); //Change to LOW if using relays
analogWrite(cosDirPin2, cosCoilValue); //comment this line out if using relays
} else {
analogWrite(cosDirPin1, cosCoilValue); //Change to HIGH if using relays
analogWrite(cosDirPin2, 0); //comment this line out if using relays
}
}
Вот данные из порта. Меряет частоту 117 (реальная 120) , но периодически всплески до 236
236
117
117
117
117
117
236
117
117
117
117
117
117
117
117
236
117
117
236
117
117
117
117
117