Подскажите пожалуйста возможные причины и их решения проблемы УЗ датчика HC-SR04.
Суть такая. Один датчик редко, но выдает значение 0, хотя расстояние нормальное, важно не само левое значение, которое можно пропустить или филтр сделать, а то что в этом случае большая задержка возникает. Второй датчик чуть ли не каждые значений 10, и при том что они довольно быстро обновляются почти каждые 2 секунда идет задержка примерно в 1 секунду. Это очень мешает, робот давно проедет предельное расстояние с такой задержкой. Код программы стандартный:
12 | unsigned int time_us=0; |
14 | unsigned int distance_sm=0; |
18 | digitalWrite(Trig, HIGH); |
20 | digitalWrite(Trig, LOW); |
21 | time_us=pulseIn(Echo, HIGH); |
22 | distance_sm=time_us/58; |
23 | Serial.println(distance_sm); |
Я когда-то делал так:
01
void
Ultrasound(){
02
digitalWrite(Trig_pin, HIGH);
03
delayMicroseconds(4);
04
digitalWrite(Trig_pin, LOW);
05
micros_old_Ult = micros();
06
while
(!digitalRead(Echo_pin) && micros()-micros_old_Ult < 500){
07
}
08
micros_old_Ult = micros();
09
while
(digitalRead(Echo_pin) && micros()-micros_old_Ult < 20000){
10
}
11
dist_cm = (micros() - micros_old_Ult)/29.0/2;
12
}
весь код здесь
Не совсем понятно приемущество этого кода, что оно дает, фильтрацию? Вы сталкивались с подобной проблемой, когда выдает ложный 0 и задержка при этом?
Думал может контакты, и на макетной плате вставлял датчик, всеравно один результат.
Задержка от того, что вы используете pulseIn, в моем коде максимальная задержка составит 20 миллисекунд и функция возвращает максимальное значение, что может расцениваться как ложный результат.
pulseIn имеет третий параметр (по умолчанию 1000000) - таймаут в микросекундах - максимально допустимое время работы функции - пользуйтесь!
Точно! Помогло поставил 25000 треим параметром.
Как дожить до вечера, чтобы проверить? Не знаю. Надеюсь, я нашел ответ, почему при пинге, если нет близкого препятствия, сканирование затыкается как раз от 0.5 до 1 секунды. Спасибо заранее :)
Если я правильно плнял, проблема в том что при близком расстоянии у вас медленно обновляется датчик или наоборот? Но это не важно.
Тогда проверяйте условие, очень вероятно что как раз в нем при близком расстоянии выполняется циккл где есть задержки (например for), они суммируются пока он полностю выполнится и получается такое долгое обновление. Таже у меня были задержки на нулях, это подсказал AlexFisher выше за что ему очень благодарен)
1
time_us1=pulseIn(Echo1, HIGH, 25000);
Вот как раз при отсутствии преград (при большом расстоянии) задержка высокая (как мне это выглядит - радар "ждет" результатов скана, но это только мое ощущение). При близком расстоянии все ок.
Было:
1
void
scanDistance() {
2
if
((millis()-oldUSTime)>=200) {
3
dist_cm = ultrasonic.Ranging(CM);
4
dist_cm = constrain(dist_cm, 0, 150);
5
oldUSTime = millis();
6
}
7
}
Стало в соотв. с топиком (точнее, вечером станет!):
1
void
scanDistance() {
2
digitalWrite(Trig, HIGH);
// Подаем сигнал на выход микроконтроллера
3
delayMicroseconds(10);
// Удерживаем 10 микросекунд
4
digitalWrite(Trig, LOW);
// Затем убираем
5
6
timeImpulseUS=pulseIn(Echo, HIGH, 25000);
// Замеряем длину импульса
7
dist_cm=timeImpulseUS/58;
// Пересчитываем в сантиметры
8
}
Предполагаю, функцию сканирования ИК-датчиком также надо будет оптимизировать. Сейчас это так:
01
void
scanIRDistance() {
02
// Если время после предыдущего скана больше 100 мс, сканируем еще раз
03
if
((millis()-oldIRTime)>=100) {
04
// ИК-сенсор
05
// 5V/1024 = 0.0048828125
06
float
volts = analogRead(IRpin)*0.0048828125;
// считываем значение сенсора и переводим в напряжение
07
float
distanceIR = 65*pow(volts, -1.10);
// worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
08
distIR = ultrasonic.Ranging(CM);
09
oldIRTime = millis();
10
}
11
}
Подозреваю, что ultrasonic.Ranging(CM) надо будет прошерстить что там в библиотеке скрыто.
Вообще, я сначала не мог понять, отчего при наличии библиотек, многие их не используют. Начинаю понимать :)))
Не используйте данный датчик. Я поймамал подобные проблемы при его использовании. Он притормаживал программу.
Я отказался от него в пользу ИК датчиков. Есть так же ультразвуковые , но это дело там решено аппаратно.
Т.е. датчик выдает либо аналоговый сигнал либо общается по UARTу.
Например вот. Правда цена там завышена.
http://www.freeduino.ru/arduino/sensor.html
Датчик тут не причем. Для проверки возьмите мой код в первом сообщении, только строчу поправить надо. Обновляется отлично.
1
time_us1=pulseIn(Echo1, HIGH, 25000);
Да, у меня HC-SR04 работает датчиком присутствия в туалете, тоже выдает нули время от времени.
Для робота, безусловно, возникающая задержка весьма критична.
Вот решение! Все никаких задержек нет, а нули можно фильтровать и все, не критично что появляются время от времени. Выше написал какую строчу поправить надо.
Удивительную вещь заметил: если питание сервы отключено и она не вращается, то УЗ-сканер нулей не выдает. Как только включаю серву, начинает сыпать нулями. Помехи?
Какие только варианты delayMicroseconds(10), delayMicroseconds(8), delayMicroseconds(4) ни пробовал, пробовал зупускать сканы не через 50мс, а через 100, 200, 400...
Сейчас буду проверять ИК-сканер... УЗ-сканер пока выполняет роль одушевления внешнего вида...
На всякий случай, вот код цикла:
01
for
(x=minAngle; x<maxAngle; x+=1) {
02
lms.servoWrite(1, x);
// Поворачиваем серву
03
delay(5);
// Даём время серве повернуть на нужный угол
04
scanDistance();
05
}
06
07
for
(x=maxAngle; x>minAngle; x-=1) {
08
lms.servoWrite(1, x);
// Поворачиваем серву
09
delay(5);
// Даём время серве повернуть на нужный угол
10
scanDistance();
11
}
Delay(5) выглядит маленьким, но если его увеличивать, серва едет очень медленно.
Функция скана:
01
void
scanDistance() {
02
if
((millis()-oldUSTime)>50) {
03
digitalWrite(Trig, HIGH);
// Подаем сигнал на выход микроконтроллера
04
delayMicroseconds(10);
// Удерживаем 10 микросекунд
05
digitalWrite(Trig, LOW);
// Затем убираем
06
07
timeImpulseUS=pulseIn(Echo, HIGH, 25000);
// Замеряем длину импульса
08
dist_cm=timeImpulseUS/58;
// Пересчитываем в сантиметры
09
//dist_cm = constrain(dist_cm, 5, 150);
10
Serial
.print(
"x: "
);
11
Serial
.print(x);
12
Serial
.print(
"|| dist_cm: "
);
13
Serial
.println(dist_cm);
14
15
oldUSTime = millis();
16
}
17
}
Источник тормозов: pulseIn(Echo, HIGH, 25000); Проверил путем комментирования данной строки. Дистанция, естественно, нульЮ но зато серва бегает без запинок!
Разбираюсь дальше...
Удивительную вещь заметил: если питание сервы отключено и она не вращается, то УЗ-сканер нулей не выдает. Как только включаю серву, начинает сыпать нулями. Помехи?
Было что-то похожее. Ну а что нули мешают? Он обновляется довольно быстро. Берешь условие задаешь и просто пропускаешь нули. А дальше испульзуешь остальные значения для какких-либо условий.
Нули мешают, т.к. при не очень частых замерах можно пропустить до 5*25 мс, а за это время в стену въехать можно, плюс, с одного борта получается слепой танк :) Плюс в момент появления нулей серва тормозить начинает (скрипт подтормаживает), поэтому появившейся предмет не успевает быть замечен танком.
В итоге, сделал как maksim "когда-то делал". Вах-вах, как все здорово работает!
Ну да тоже как вариант, хотя у меня быстрое обновление, и 0 вообще не мешают.
Друзья!
У меня вот такая проблема:
Датчик HC-SR04 с Arduino UNO сам по себе работает достаточно стабильно, также, стабильно работает вместе с сервой TowerPro 9G, но как только я собираю все вместе с Motor Drive на L298 - начинается путаница. Моторы не крутятся, Ultrasonic возвращает только "0", серва работает нормально.
Опытным путем вычислил, что убирая серву, Ultrasonic HC-SR04 начинает давать показания с некоторыми ошибками, но не "0". Ниже привожу свой код:
001
#include <Servo.h>
002
#include <IRremote.h>
003
#include <NewPing.h>
004
005
006
// ULTRASONIC PINS
007
#define TRIGGER_PIN 13 // yellow
008
#define ECHO_PIN 12 // orange
009
#define MAX_DISTANCE 500
010
011
#define MIN_DISTANCE 26
012
013
// SERVO PINS
014
#define SERVO_PIN 7 // orange
015
016
// IR PINS
017
#define IR_PIN 11 // yellow
018
019
// MOTOR SHIELD PINS
020
#define ENA_PIN 9 // black
021
#define ENB_PIN 10 // white
022
#define IN1_PIN 2 // gray BACK
023
#define IN2_PIN 3 // violet FORWARD
024
#define IN3_PIN 4 // blue FORWARD
025
#define IN4_PIN 5 // green BACK
026
027
boolean OPERATION =
true
;
028
unsigned
int
DISTANCE = 0;
029
// boolean LDir = true, RDir = true; // true = Forward, false = Backward
030
int
LSpeed = 0, RSpeed = 0;
031
boolean Changes =
false
;
032
033
034
NewPing ultrasonic(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
035
036
Servo servoDrive;
037
038
IRrecv ir(IR_PIN);
039
decode_results irResult;
040
041
int
getAngleArray(
void
);
042
unsigned
int
getDistance(
void
);
043
044
// void TURNL(int);
045
// void TURNR(int);
046
void
TURNB(
void
);
047
void
TURNF(boolean, unsigned
int
);
048
void
STOP(
void
);
049
// ---------------------------------------------------------------------------------
050
051
// ----------------------- SETUP BEGIN ---------------------------------------------
052
void
setup
() {
053
Serial
.begin(115200);
054
055
servoDrive.attach(SERVO_PIN);
// SERVO Initialisation
056
057
ir.enableIRIn();
// IR Initialisation
058
059
// MOTOR Initialisation
060
pinMode(6, OUTPUT);
// ---- Dir 1 ---------
061
pinMode(7, OUTPUT);
// ---- Dir 2 ---------
062
pinMode(10, OUTPUT);
// ---- ENA -----------
063
064
pinMode(8, OUTPUT);
// ---- Dir 1 ---------
065
pinMode(9, OUTPUT);
// ---- Dir 2 ---------
066
pinMode(11, OUTPUT);
// ---- ENB -----------
067
068
servoDrive.write(90);
069
}
070
// ------------------------- END SETUP ---------------------------------------------
071
072
073
// ------------------------ LOOP BEGIN ---------------------------------------------
074
void
loop
() {
075
if
(ir.decode(&irResult)) {
076
switch
(irResult.value) {
077
case
0xFF02FD:
078
if
(OPERATION ==
false
) OPERATION =
true
;
else
OPERATION =
false
;
079
080
Changes =
true
;
081
082
break
;
083
// ---------------------- oter cases -----------------------------------------
084
085
// ---------------------- oter cases -----------------------------------------
086
}
087
ir.resume();
088
}
089
//delay(100);
090
091
DISTANCE = getDistance();
092
093
if
(DISTANCE < MIN_DISTANCE) Changes =
true
;
094
095
if
(Changes ==
true
) TURNF(OPERATION, DISTANCE);
096
097
}
098
// ------------------------ END LOOP -----------------------------------------------
099
100
void
STOP() {
101
analogWrite (ENA_PIN, 0);
102
digitalWrite (IN1_PIN, LOW);
103
digitalWrite (IN2_PIN, LOW);
104
105
analogWrite (ENB_PIN, 0);
106
digitalWrite (IN3_PIN, LOW);
107
digitalWrite (IN4_PIN, LOW);
108
}
109
110
void
TURNF(boolean operation, unsigned
int
distance) {
111
112
if
(operation ==
false
) {
113
STOP();
114
115
Changes =
false
;
116
return
;
117
}
118
119
if
(operation ==
true
&& (distance > MIN_DISTANCE || distance == 0)) {
120
//delay (100);
121
analogWrite (ENA_PIN, 255);
122
analogWrite (ENB_PIN, 255);
123
//delay (500);
124
digitalWrite (IN1_PIN, LOW);
125
digitalWrite (IN2_PIN, HIGH);
//FORWARD
126
digitalWrite (IN3_PIN, HIGH);
//FORWARD
127
digitalWrite (IN4_PIN, LOW);
128
129
Changes =
false
;
130
return
;
131
}
132
133
if
(operation ==
true
&& distance <= MIN_DISTANCE) {
134
STOP();
135
136
// FIND NEW DIRECTION !!!!!!!
137
int
optAngle = getAngleArray();
138
139
Changes =
false
;
140
return
;
141
}
142
}
143
144
int
getAngleArray() {
145
unsigned
int
Angles[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
146
unsigned
int
rDistance = 1;
147
int
rangle = 90;
148
for
(
int
a = 0; a <= 18; a++) {
149
servoDrive.write(a * 10);
150
//delay(50);
151
152
Angles[a] = getDistance();
153
}
154
155
for
(
int
a = 0; a <= 18; a++) {
156
if
(Angles[a] > rDistance) {
157
rDistance = Angles[a];
158
rangle = a * 10;
159
}
160
}
161
servoDrive.write(90);
162
163
164
if
(rangle < 90)
return
-(90 - rangle);
165
if
(rangle > 90)
return
rangle - 90;
166
if
(rangle == 90)
return
0;
167
168
}
169
170
unsigned
int
getDistance() {
171
delay(100);
172
unsigned
int
uS = ultrasonic.ping();
// Send ping, get ping time in microseconds (uS).
173
Serial
.print (
"getDistance = "
);
174
Serial
.println (uS / US_ROUNDTRIP_CM);
175
return
(uS / US_ROUNDTRIP_CM);
176
177
}
Идея банальная. С пулта ИК даем команлу на запуск. Робот едет вперед пока сенсор приближения не покажет расстояние 26. Останавливаемся перед препятствием, ищем оптимальный угол поворота, поварачиваем (не добрался до этого места) едем дальше.
Ведет себя схема по-дурацки. Пока едет прямо, очень часто получает результат "4" от Ultrasonic. Ищет угол поворота нормально, но только доходит дело до движения прямо, опять getDistance() возвращает "4". Бред. Не поможите?
Чем и как все это дело питаете?
Спасибо за отклик.
Пробовал разные варианты:
1. От двух аккумуляторов по 3,7В всю схему
2. Моторы от аккумов, логику от USB (земли естественно соединял)
3. Всю схему от USB (ради прикола)
4. Всю логику от USB, без питания двигателей
Эффект всегда одинаковый
P.S. Шунты на движки не ставил, но моя проблемя есть даже с отключенными движками (включена только логика драйвера моторов)
Интересно как вообще у вас это работает... вот вы определили выводы:
1
#define ENA_PIN 9 // black
2
#define ENB_PIN 10 // white
3
#define IN1_PIN 2 // gray BACK
4
#define IN2_PIN 3 // violet FORWARD
5
#define IN3_PIN 4 // blue FORWARD
6
#define IN4_PIN 5 // green BACK
а на выход настроили из них только 10 и 9:
1
pinMode(6, OUTPUT);
// ---- Dir 1 ---------
2
pinMode(7, OUTPUT);
// ---- Dir 2 ---------
3
pinMode(10, OUTPUT);
// ---- ENA -----------
4
5
pinMode(8, OUTPUT);
// ---- Dir 1 ---------
6
pinMode(9, OUTPUT);
// ---- Dir 2 ---------
7
pinMode(11, OUTPUT);
// ---- ENB -----------
правильно было бы так:
1
pinMode(ENA_PIN, OUTPUT);
2
pinMode(ENB_PIN, OUTPUT);
3
pinMode(IN2_PIN, OUTPUT);
4
......
то же самое :
1
#define IR_PIN 11 // yellow
и настраиваете его на выход:
1
pinMode(11, OUTPUT);
Sorry! Спасибо за подсказку!
Это уже измененный код после экспериментов со сменой выходов. Когда для моторов были назначены пины 2 3 4 5 9 10 схема не работала. Крутился только один мотор а на выходе другой шины горели светодиоды, как если бы я прописал:
1
digitalWrite (4, LOW);
2
digitalWrite (5, HIGH);
3
digitalWrite (2, HIGH);
4
digitalWrite (3, HIGH);
Сейчас проблема не в моторах, я их вообще отключил. Проблема в том, что в зависимости от места откуда я вызываю одну и ту же функцию getDistance(); она возвращает то правильные, то неправильные значения.
При вызове из loop() я постоянно получаю "4" независимо от реального расстояния
01
void
loop
() {
02
if
(ir.decode(&irResult)) {
03
switch
(irResult.value) {
04
case
0xFF02FD:
05
if
(OPERATION ==
false
) OPERATION =
true
;
else
OPERATION =
false
;
06
07
Changes =
true
;
08
09
Serial
.print (
"OPERATION = "
);
10
Serial
.print (OPERATION);
11
Serial
.println ();
12
break
;
13
// ---------------------- oter cases -----------------------------------------
14
15
// ---------------------- oter cases -----------------------------------------
16
}
17
ir.resume();
18
}
19
//delay(100);
20
Serial
.println (
"loop"
);
21
DISTANCE = getDistance();
// ЗДЕСЬ Я ПОЛУЧАЮ 4
22
23
if
(DISTANCE < MIN_DISTANCE) Changes =
true
;
24
25
if
(Changes ==
true
) MOVE(OPERATION, DISTANCE);
26
27
}
А ниже:
01
int
getAngleArray() {
02
unsigned
int
Angles[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
03
unsigned
int
rDistance = 1;
04
int
rangle = 90;
05
for
(
int
a = 0; a <= 18; a++) {
06
servoDrive.write(a * 10);
07
//delay(50);
08
Serial
.print (
"Angle = "
);
09
Serial
.print (a * 10);
10
Serial
.print (
" "
);
11
Angles[a] = getDistance();
// ЗДЕСЬ Я ПОЛУЧАЮ ПОЧТИ РЕАЛЬНЫЕ РАССТОЯНИЯ
12
}
13
14
for
(
int
a = 0; a <= 18; a++) {
15
if
(Angles[a] > rDistance) {
16
rDistance = Angles[a];
17
rangle = a * 10;
18
}
19
}
20
servoDrive.write(90);
21
22
Serial
.print (
"OPTIMAL ANGLE = "
);
23
Serial
.print (rangle);
24
Serial
.print (
" MAX DISTANCE = "
);
25
Serial
.println (rDistance);
26
27
if
(rangle < 90)
return
-(90 - rangle);
28
if
(rangle > 90)
return
rangle - 90;
29
if
(rangle == 90)
return
0;
30
31
}
Я получаю иногда "0", а иногда реальное расстояние в СМ.
В общем проблему решил!
Оказалась серва с криво выставленным потенциком. Разобрал, выставил центр, собрал, все заработало как надо. Теперь буду разбираться с движками.
Спасибо Максу за участие.
Немного обновим тему.
Имеем датчик SR04T, для теста использую примерно следующий код
1
digitalWrite(Trig, HIGH);
2
/* Подаем импульс на вход trig дальномера */
3
delayMicroseconds(10);
// равный 10 микросекундам
4
digitalWrite(Trig, LOW);
// Отключаем
5
impulseTime=pulseIn(Echo, HIGH, 25000);
// Замеряем длину импульса
Возник непонятный баг, при заливке тестового скетча все работает нормально, но при вставке кода в рабочий скетч, pulseIn почему то снижает показания примерно на треть. Самое пикантное, что при использовании кода от maksim показания нормальные.
В отличие от датчика ТС, этот датчик периодически выдает в качестве помехи не 0, а максимальное значение, что то типа 17423 мкс. Датчик будет использоваться в ограниченном пространстве поэтому импульсы длиннее определенной величины просто игнорирую. Есть ньюанс, в слепой зоне (ближе 20 см) датчик выдает случайные значения, а в упор к препятствию - опять максимальное значение. Поэтому если датчик постоянно выдает это значение (либо заранее снижаю планку), принимаю его за 0.
Более менее нормально работает примерно такой код
01
#define Trig 6
02
#define Echo 4
03
#define K_TIMER 29
04
05
unsigned
int
UltraSoundMicros(unsigned
int
Max_Distance)
06
{
07
unsigned
long
int
_Time;
08
unsigned
long
micros_old_Time;
09
10
for
(uint8_t i=0; i<8; i++)
//делаем несколько попыток чтения
11
{
12
digitalWrite(Trig, HIGH);
13
delayMicroseconds(10);
14
digitalWrite(Trig, LOW);
15
micros_old_Time = micros();
16
while
(!digitalRead(Echo) && micros()-micros_old_Time < 500){ }
17
micros_old_Time = micros();
18
while
(digitalRead(Echo) && micros()-micros_old_Time < 20000){ }
19
_Time = (micros() - micros_old_Time);
20
if
(_Time<Max_Distance)
break
;
// при нормальной длине импульса прерываем цикл
21
if
(i) delay(100);
22
}
23
24
if
(_Time>=Max_Distance) _Time=0;
//Слишком близко, все импульсы длинные
25
return
_Time/K_TIMER;
26
27
}
У меня пахожая проблема возникла с этими датчиками вот тут: http://arduino.ru/forum/programmirovanie/pomogite-s-chastyu-koda-vyklyuc... оказывается что эти датчик имееют разброс пораметров, один у меня нормальный попался, а др. вообще как то вяло работает и сигнал угасает в одежде.
Пес его знает, как там
pulseIn
реализован, похоже дело в таймерах. У меня ИК приемник использует, других видимых причин не нашел пока. Крайне неохота проверять, уже к другому делу перешел.тоже мучаюсь ((( скачит на 1 см постоянно и это при использованиии формулы maksim с первого поста
тоже мучаюсь ((( скачит на 1 см постоянно и это при использованиии формулы maksim с первого поста
Так это ж погрешность дискретизации при обработке. При чем здесь датчик?
Какой используется тип переменной?
01
Перехлеснулись мы свами))
02
Использую получается
float
иначе не отображает потом на экране ничего
03
вот соединеный вариант скеча не сохранил((
04
Но отображение взял с этого скетча а формулу с поста 1
05
06
07
08
[code]
09
10
#include <SPI.h>
11
//#include <Wire.h>
12
#include <OLED_I2C.h>
13
OLED myOLED(52, 49, 52);
//пины дисплея
14
extern
uint8_t RusFont[];
// Русский шрифт
15
extern
uint8_t MegaNumbers[];
// Подключение больших шрифтов
16
extern
uint8_t SmallFont[];
// Базовый шрифт без поддержки русскийх символов.
17
float
daln;
18
19
#include <Ultrasonic.h>
20
Ultrasonic ultrasonic(8,9);
//trig 8 , exo 9
21
22
void
setup
(){
23
myOLED.begin();
24
myOLED.setFont(RusFont);
25
pinMode(8, OUTPUT);
26
pinMode(9, INPUT);
27
}
28
29
void
loop
() {
30
float
daln = ultrasonic.Ranging(CM);
31
myOLED.clrScr();
// Стираем все с экрана
32
myOLED.setFont(RusFont);
33
myOLED.print(
"HFCCNJZYBT"
, CENTER, 1);
// Выводим надпись "расстояние"
34
myOLED.setFont(MegaNumbers);
35
myOLED.print(String (daln, 1), CENTER, 15);
// Отображение значения растояния
36
myOLED.update();
37
delay(500);
38
}
39
[/code]
как же правильно все таки усреднить показатели? чтоб не скакал
как же правильно все таки усреднить показатели? чтоб не скакал
Это, смотря чего Вы хотите добиться.
Если именно чтобы железно не скакал - отображайте все время одну и ту же цифру, не имеющую отношения к измеряемому параметру. Скакать не будет совсем.
Если же требуется отображать реальную величину, "скачки" неизбежны - хотя бы при изменении измеряемой величины.
Более того, если, скажем, Вы округляете до целых, то при знечении вблизи полуцелого (т.е. типа 1.5, 3.5, 18.8) усреднение не способно избавить Вас от "скачков". В этом случае нужно вводить гистерезис. Допустим, примем величину гистерезиса 0.2. Тогда, скажем, если индицируется 17, то переключаться на 16 - при показаниях не более 16.3, а на 18 - не менее 17.7.
Ну что-то подобное. Хотелось бы просто видеть сантиметры которые не будут скакать до величины хотя бы 0.5см., особая точность ведь не требуется. Почитав тему вот и использовал выше приведенный скетч (скетчи)
Посчитайте разброс датчика и усредняйте значения, за N измерений, что бы не скакали. У меня практика показала, что измерния не скачут, если их измерять в см (unsigned int). Измерения веду посредством millis(). Помехи в виде величины, превыщающей некий максимальный предел я отбрасываю.
Попробовал 2-3 примера с разных источников, везде значения пляшут. Только когда препятствие находится в диапазоне до 40-50см, все стабильно и точно. Я не программер, могу только что-то в скетче подправить под себя.
Может, кто подскажет похожий под такую задачу:
Точка контроля - плакат. Надо включать свет, когда у плаката остановились его посмотреть. Помехи - проезжающие машины, проходящие люди.
Алгоритм вроде простой при корректно работающем датчике: замеряешь расстояние до препятствия и оцениваешь время, когда расстояние меньше двух метров измеряется больше 2-3 секунд. Если больше - с выхода пошел импульс, и система не воспринимает изменения в течении 2-3 минут. После чего опять начинается контроль расстояния.
Но датчик сыпет через два нормальных замера фейковые значения, и чего с этим делать, не пойму. На то, что замер не будет меняться, тоже рассчитывать не стоит, человек же не как вкопанный стоит, шевелится. Никаких идей нет?
>Помехи - проезжающие машины, проходящие люди.
это не помехи, они вне диапазона действия датчика (дальше 2-х м).
>датчик сыпет через два нормальных замера фейковые значения, и чего с этим делать, не пойму
вариант а) завести величину k, равную где-то 1/5...1/10 от измеряемой дистанции. В процессе измерений сравнивать разность между текущим и предыдущим значением. Если оно превышает k (в любую сторону) считать текущее измерение фейковым и не обрабатывать его.
вариант б) использоваль програмный фильтр Калмана. Он делает практически то же самое что и предыдущий вариант, но по другому алгоритму.
Да, так фильтровать, наверное, можно. Буду стучаться к людям, кто может это написать.
Что касается диапазона - таки нет, датчик весьма корректно мерил растояние до стены напротив, 342см, причем именно это значение и чередовалось с мусором - то 342, то 4. Руку подставляешь, и он меряет искомые 20-30см как вкопанный. То есть не может устойчиво замерять большие расстояния
SergAG, попробуйте ещё мой вариант на асме:)
Спасибо, попробую. А в 1.0.6. не скомпиллируется?
...Нет, не идет
Попробовал 2-3 примера с разных источников, везде значения пляшут. Только когда препятствие находится в диапазоне до 40-50см, все стабильно и точно. Я не программер, могу только что-то в скетче подправить под себя.
Может, кто подскажет похожий под такую задачу:
Точка контроля - плакат. Надо включать свет, когда у плаката остановились его посмотреть. Помехи - проезжающие машины, проходящие люди.
Алгоритм вроде простой при корректно работающем датчике: замеряешь расстояние до препятствия и оцениваешь время, когда расстояние меньше двух метров измеряется больше 2-3 секунд. Если больше - с выхода пошел импульс, и система не воспринимает изменения в течении 2-3 минут. После чего опять начинается контроль расстояния.
Но датчик сыпет через два нормальных замера фейковые значения, и чего с этим делать, не пойму. На то, что замер не будет меняться, тоже рассчитывать не стоит, человек же не как вкопанный стоит, шевелится. Никаких идей нет?
SergAG, скажите, Вы - писатель?
Если "нет", то я полагаю, Вы нашли на просторах И-нета текст, котрый я выше отквотил, заменили в нем прд себя пару слов и разместили на этом форуме.
Я прав?
Я, если честно, ничего не понял. Видимо, тут какая-то ирония. В смысле что нестабильность уз - холивар? Может быть. Поиском прошелся, несколько форумов нашел, но аккаунт только здесь, тут и спросил. Я чего-то не догоняю, в чем проблема? В чем Вы должны быть правы?
Проблема видимо в нежелании догонять, ибо это требует "разобраться" с вопросом. Скачать кучку скетчей, по большей части одинаковых на просторах сети может даже что-то попробовать и затем вот так обобщать - большого ума не требует. Вам dimax дал код который использовался для работы анемометра, если Вы его хотя бы смотрели, в чем лично я - уже сильно сомневаюсь, ибо там достигнутая точность-стабильность = 1 ТАКТ микроконтроллера. Это даже не "поверочный прибор" (если вам такое слово знакомо, нет - гуглите). Вы его даже не опробовали .. а между прочим, там есть где компилится, как .. но, нет жеж! Вы заново задаете вопрос впустую...
В сети и на этом форуме даже, выложены мои эксперименты по этому датчику. Для перпендикулярной поверхности датчик устойчиво работает с ошибкой менее 1мм на всем диапазоне расстояний от 3см до 5метров .. нашли, пробовали? Сдается мне что нет. А кроме того! Там показана АСИНХРОННАЯ работа с датчиком, когда скетч не "зависает" на время ожидания и измерения импульса .. Andriano, похоже прав .. чукча - писатель.
Датчик в целом, работает ровно так, как Вы его попросите. У него есть проблемы, но иные: он может запросто ловить боковое препятствие, в боковом лепестке; есть версии периодически теряющие напругу и их надо перезапускать "с толкача"; есть ловля первого сигнала от дальнего препятствия при ограничении времени ожидания и частом опросе - ограничив дальность скажем 4мсек, и опрашивая каждые 4мсек можно легко словить импульс от первого опроса при втором.. но, если им правильно пользоваться то показания стабильны и точность измерений менее 1мм. Проверено не на раз.
2Arhat109-2 Что я знаю, что я пробовал и в чем мое желание - оставьте эти мнения при себе. Тем более то, чего Вам "сдается". Бред какой-то, еще один препод нарисовался. Еще и хамоватый. Перейдете на другой тон - напишу, какие скетчи пробовал, где их искал, на каком железе, и какие результаты получил. А в таком тоне могу только на улице разговаривать.
Думаете мне оно интересно что вы пробовали а что нет? Датчик НАДЕЖНО работает с точностью до 1мм в рабочем диапазоне расстояний. Все остальное - кривые руки. Перечитайте и проверьте свои результаты. Как получится - пишите. :)
Мой сын в свои 11 лет - справляется и это вообще его любимый датчик. У вас тоже получится, я уверен.
2Arhat109-2 Что я знаю, что я пробовал и в чем мое желание - оставьте эти мнения при себе. Тем более то, чего Вам "сдается". Бред какой-то, еще один препод нарисовался. Еще и хамоватый. Перейдете на другой тон - напишу, какие скетчи пробовал, где их искал, на каком железе, и какие результаты получил. А в таком тоне могу только на улице разговаривать.
Мил-человек! Это ж у тебя проблемма с УЗ датчиком, а не у Архата, У него, у меня, у Димы и у других - нет проблемм с этим датчиком. Тон не тебе выбирать. Высокомерие и глумеж - считай это плата за ответ на вопрос. Не нравится - скатертью по жопе. Найдешь ответы "на улице", по твоему меткому выражению.
Я доступно излагаю? В теме, кудал ссылку Дима есть все нужные ответы. Цифровой фильтр мусора - есть много где, на помехе по питанию заканчивается та тема. Sapienti sat!
О-па! Еще один герой... Не был бы здесь не первый год, подумал бы, тут все такие. А это новенький, оказывается. Не обтесался еще. Спишем эту удаль на издержки виртуального пространства. wdrakula, это не моя ветка, поэтому не могу попросить Вас покинуть ее, но давайте адекватнее выбирать плату за глупые вопросы, тут таких больше, чем умных. Ваш, кстати, тоже. По крайней мере, отвечать на Ваши посты я больше не буду.
Arhat109-2, а в чем причина такой реакции? я ведь действительно здесь не первый год, но такого эпатажа не было. Я не комплексую, когда меня учат, тем более, в этих вопросах руки у меня действительно кривые. У меня нет сомнений, что датчик может работать. Как и все остальные пара десятков девайсов, которые у кого-то работают, у кого-то нет. Эти первые чем-то помогают этим вторым. Или ничего не пишут. А тут, кроме dimax (уже не первый раз он мне подсказывает решение, ну в этот раз я не смог его реализовать), столько букв народ написал, и ни о чем.
[quote=SergAG]
не могу попросить Вас покинуть ее, но давайте адекватнее выбирать плату за глупые вопросы, тут таких больше, чем умных. Ваш, кстати, тоже.
[quote]
1. Просить будешь папу, если с ним знаком. Вдруг.
2. Я НИКОГДА не задавал никаких вопросов на форум-е (-ах). Это основная причина того, что я считаю задающих мудлом. Всех. На любой вопрос можно найти ответ самому. На всех форумах, где я бываю - я только отвечаю. Тем, кого считаю достойным моего внимания. Сорри за высокомерие. Надите собеседника с IQ > 160 - мне будет о чем с ним говорить.
3. с 2012 года пора бы уже чему-то научиться в своем хобби. Я не равняю с собой - я профессиональный математик. Но даже любителю пяти лет хватит.
4. Иди в жопу.
Вот черт, не удержаться! Извини, больше не буду, но сейчас не могу не задать вопрос: а тебе действительно так хорошо знаком маршрут по п.4? Ты уже дважды его пытаешься мне рекомендовать. Тебе там так понравилось? Можно , я воздержусь, не хочу быть твоим соседом ))))
Дальше тоже можно было бы, типа люди с высоким интеллектом этим не кичатся (соответственно, если кичатся, то...), ну и еще дальше, если вопросов не задаешь, и по существу не отвечаешь то чего ты тут вообще делаешь? Писатель?
Все. Пришел кот Леопольд, и наказал жить дружно. Расслабься, я больше участвовать в пикировках не буду.
пока спать не пошел.
Сорри.
Но ты смотрел ту тему, куда тебе Дима ссылку дал?
Тема мне знакомая.
Там же есть все ответы.
Редкие помехи SR04 дает при нечистом питании. На этом закончилась та тема.
При решенных вопросах питанияеЕсть чистая фильтрация выбросов. Это мат-статистика. Попроси помочь - помогу. Делаешь несколько замеров, выкидываешь "выбросы", остальное - усредняешь.
--------------------------------------------------
Я поясню на что я "завелся" - на хамство Архату.
Я с Архатом очень много и резко ругался,но он очень хороший интуитивный программист. Не стоит так с ним разговаривать. У него в самом деле этим датчиком 11-и летний ребенок управляет. Если у тебя регистрация с 2012 года - просто почитай, кто-тут-кто теперь.
Да я - по вечерам всегда пьян и груб. Утром - могу ответить более адекватно. Уж прости. Мне 47 лет и меняться поздно.