датчик VL53L0x-v2 иногда передает значение 65535
- Войдите на сайт для отправки комментариев
Всем добрый вечер, делаю проект: радиомашинка, с двумя инфракрасными датчиками, сервоприводом, драйвером двигателей l298n и блютуз модулем HC-06. Суть проекта, чтобы машинка автоматически находила середину дороги и сервопривод нажимал на балончик с краской. Проблема следующая: при чтении с инфракрасных датчиков иногда приходит значение 65535 и дальше програма работает некорректно, 1 датчик перестает видеть и приходит только 65535. Недавно сделал проверку адреса регистра (в програме меняю адрес для двух инфракрасных датчиков) и при проверке обнаружило 4 устройства на шине і2с, вместо двух.
Буду очень признателен если ктото объяснит почему приходит 65535 или как решить проблему с 4 устройствами і2с вместо 2. И вообще посоветует как програму улучшить, спасибо заранее, и простите, если совершил ошибки в тексте.
Вот большая часть моей програмы:
#include <Servo.h> #include <SoftwareSerial.h> #include <Wire.h> #include <VL53L0X.h> char incomingByte; // входящие данные SoftwareSerial mySerial(10, 11); // RX, TX int IN1 = 5; //сірий int IN2 = 4; //білий int IN3 = 3; //жовтий int IN4 = 2; //коричнивий unsigned int x; unsigned int y; int Servopin = 9; VL53L0X sensor; VL53L0X sensor2; Servo Servo1; void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); digitalWrite(6, LOW); digitalWrite(7, LOW); delay(500); Servo1.attach(Servopin); Serial.begin(9600); Servo1.write(60); sensor.setTimeout(500); sensor2.setTimeout(500); Wire.begin(); mySerial.begin(9600); pinMode(6, INPUT); delay(150); mySerial.println("00"); sensor.init(true); mySerial.println("01"); delay(100); sensor.setAddress((uint8_t)22); mySerial.println("02"); pinMode(7, INPUT); delay(150); sensor2.init(true); mySerial.println("03"); delay(100); sensor2.setAddress((uint8_t)25); mySerial.println("04"); mySerial.println("addresses set"); sensor.setSignalRateLimit(0.1); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); sensor.setMeasurementTimingBudget(200000); sensor2.setSignalRateLimit(0.1); sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); sensor2.setMeasurementTimingBudget(200000); } void loop() { if (mySerial.available() > 0) { //если пришли данные incomingByte = mySerial.read(); // считываем байт if (incomingByte == '9') {//Scan mySerial.println ("I2C scanner. Scanning ..."); byte count = 0; for (byte i = 1; i < 200; i++) { Wire.beginTransmission (i); if (Wire.endTransmission () == 0) { mySerial.print ("Found address: "); mySerial.print (i, DEC); mySerial.print (" (0x"); mySerial.print (i, HEX); mySerial.println (")"); count++; delay (1); } } mySerial.println ("Done."); mySerial.print ("Found "); mySerial.print (count, DEC); mySerial.println (" device(s)."); delay(1000); }
if (incomingByte == '+') {//Range x = sensor.readRangeSingleMillimeters(); mySerial.print(x); if (sensor.timeoutOccurred()) { mySerial.print(" TIMEOUT"); } mySerial.println(); y = sensor2.readRangeSingleMillimeters(); //присвоюються х mySerial.print(y); if (sensor2.timeoutOccurred()) { mySerial.print(" TIMEOUT"); } mySerial.println(); } if (incomingByte == '#') {//Auto x = sensor.readRangeSingleMillimeters(); //присвоюються х mySerial.print(x); mySerial.println(); y = sensor2.readRangeSingleMillimeters(); //присвоюються y mySerial.print(y); mySerial.println(); if ( x > y ) { while ( x > y ) // Якщо відстань зліва більша від відстані справа { mySerial.println ("Зліва більша"); x = sensor.readRangeSingleMillimeters(); //присвоюються х mySerial.print(x); mySerial.println(); y = sensor2.readRangeSingleMillimeters(); //присвоюються y mySerial.print(y); mySerial.println(); if ((abs( x - y ) > 5000 ) && (abs( x - y ) < 7000 ) ) //якщо модуль різниці зліва і справа в межах 5000 7000 { mySerial.println ("від 7 до 5 м"); digitalWrite(IN1, HIGH); delay(1000); //частковий поворот вправо digitalWrite(IN3, HIGH); delay(1000); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); digitalWrite(IN2, HIGH); delay(1000); digitalWrite(IN3, HIGH); delay(1000); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); } if ((abs( x - y ) > 2000 ) && (abs( x - y ) < 5000 ) ) //якщо модуль різниці зліва і справа в межах 2000 5000 {mySerial.println ("від 5 до 2 м"); digitalWrite(IN1, HIGH); delay(1000); digitalWrite(IN3, HIGH); delay(500); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); digitalWrite(IN2, HIGH); delay(1000); digitalWrite(IN3, HIGH); delay(700); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); } if ( (abs(x - y ) > 50 ) && ( abs(x - y) < 2000 ) ) //якщо модуль різниці зліва і справа в межах 50 2000 {mySerial.println ("від 50 до 2 м"); digitalWrite(IN1, HIGH); delay(400); digitalWrite(IN3, HIGH); delay(500); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); digitalWrite(IN2, HIGH); delay(50); digitalWrite(IN3, HIGH); delay(200); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); } if ( abs(x - y) <= 50 ){ mySerial.println ("Середина досягнута"); digitalWrite(IN2, HIGH); delay(400); digitalWrite(IN3, HIGH); delay(400); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); break;} if ( y > x) { mySerial.println ("y > x"); break;} if (mySerial.available() > 0) { //если пришли данные incomingByte = mySerial.read(); if(incomingByte == '0') { break; } }}} if ( y > x ) { while ( y > x ) // Якщо відстань справа більша від відстані зліва { mySerial.println ("Справа більша"); x = sensor.readRangeSingleMillimeters(); //присвоюються х mySerial.print(x); mySerial.println(); y = sensor2.readRangeSingleMillimeters(); //присвоюються х mySerial.print(y); mySerial.println(); if ((abs( y - x) > 5000 ) && (abs(y - x) < 7000 ) ) { digitalWrite(IN2, HIGH); delay(1000); digitalWrite(IN3, HIGH); delay(1000); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN1, HIGH); delay(1000); digitalWrite(IN3, HIGH); delay(1000); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); } if ((abs( y - x ) > 2000 ) && ( abs( y - x ) < 5000 ) ) { digitalWrite(IN2, HIGH); delay(200); digitalWrite(IN3, HIGH); delay(500); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN1, HIGH); delay(200); digitalWrite(IN3, HIGH); delay(700); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); } else if ((abs( y - x ) > 50 ) && ( abs(y - x) < 2000 ) ) { digitalWrite(IN2, HIGH); delay(400); digitalWrite(IN3, HIGH); delay(400); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN1, HIGH); delay(50); digitalWrite(IN3, HIGH); delay(200); digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); } if (abs( y - x ) <= 50) { mySerial.println ("Середина досягнута"); digitalWrite(IN3, HIGH); // Вперед delay(500); digitalWrite(IN3, LOW); break;} if ( x > y) { mySerial.println ("x > y"); break;} } } }}}
Также у меня в текстовый документ переносяться пришедшие данные и вот что высветилось при считывания регистров і2с
Ну так таймаут никто не считывает. Он сам приходит когда датчик ошибается. Это надо обрабатывать. Например вставить проверку что если пришло 65535 то ничего не делать а ждать следующего измерения.
Приблизительный результат работы системы, до того как оказалось 4 регистра і2с:
Таймаут считываеться только при обычном считывании растояния, там ошибок не возникает, а ошибка 65535 только в автопоиске середины и тогда и датчик один перестает видеть програма для считывание регистров
У вас есть функция timeoutOccurred. Проверяйте её перед вызовом замера. Пока она true ничего мерить не будет.
это как вариант решения, но если придет 65535 все равно работать не будет система, потому что 65535 прекращало показывать лишь после перезагрузки системы через кнопку на плате
У вас слишком быстро крутится цикл while. Не хотите проверять свободен датчик или нет, вставте задержку после первого чтения больше таймаута. Иначе вы не сработавший датчик пинаете снова и он зависает.
Спасибо, попробовать нужно, задержку добавить через delay?
Если у Вас схема чуть сложнее, чем единственный датчик, лучше пользоваться millis().
Спасибо, сейчас попробую
Вопрос от юзера верно ли я предполагаю:
чи так
С millis() не получилось, а при опросе timeoutOccurred
no matching function for call to 'VL53L0X::timeoutOccurred(int)'
if ((sensor.timeoutOccurred(false)) || (sensor2.timeoutOccurred(false))) выдает следующее:
попробую через else if, теперь до if ((sensor.timeoutOccurred(true)) || (sensor2.timeoutOccurred(true))) прицепилось с тем же
Всем доброй ночи, получилось с millis() но както не верно, один раз считываються показания x и y (инфракрасных датчиков), а второй раз уже пропускаються и сразу идет движение, если кто может, очень прошу разьясните в чем проблема, спасибо
и вот что считывала програма
Поиск в файле VL53L0X.cpp :
понял, про таймаут писали, признаю я виноват
Спасибо большое, хороший совет
Проблема не в том, что приходит значение 65535, а в том, что оно приходит после сбоя регистра правого ( возможно иногда и левого) лазерного дальномера при автопоиске середины, я попробовал сделать паузы через millis, завтра скину финальный вариант, и если вам не в тягость, тыкните пальцем где я ошибся, там цикл проходит много раз, но упускаеться проверка значений из датчиков после первого цикла, спасибо
Как вариант может в while поместить чтобы сторона начала движения определялась (слева на право к середине или наоборот)? И действия происходили по выравниванию, тогда на 1 while было бы меньше
Вот код з Milles помилка в частині Auto:
Вот как действовала програма:
Я не сильно уверен в том что можно два инфракрасных , ультразвуковых или лазерных датчика
одновременно направить в одну точку
и потом успешно, без взаимного влияния, ловить отражённый сигнал.
Я не сильно уверен в том что можно два инфракрасных , ультразвуковых или лазерных датчика
одновременно направить в одну точку
и потом успешно, без взаимного влияния, ловить отражённый сигнал.
Спасибо за ваш комментарий, у меня два лазерных дальномера "смотрят" в разные стороны, тоесть справа и слева радиоуправляемой машинки, они должны измерить два значения и проанализировал где больше, машинка подъезжает в нужную сторону чтобы ближе к середине
Я, дурак, придумал себе такую тему на магистерскую и теперь "сушу" мозги себе и вам
Ну, это Вы напрасно сказали. Большинство здесь присутствующих нерадивым студентам не помогают. Думаю, сейчас Вы быстро заметите отток желающих помочь :)
Ну, это Вы напрасно сказали. Большинство здесь присутствующих нерадивым студентам не помогают. Думаю, сейчас Вы быстро заметите отток желающих помочь :)
Я сказал все как есть на самом деле, зачем мне лгать кому то, практика работы с ардуино у меня всего 1.5 года
Попробую delay что между считаваниями заменить на smart delay, может поможет както https://habr.com/post/319184/
и так, проблема точно в delay() он точно сбивает правый регистр датчика 25 (0х19) на 41 (0х29) это стандартный, я пробовал менять на 41 правый, не помогло, 65535 так и пришли, програма делает 1 цикл, а при втором, во время считывания правого датчика "y" - 65535, а вопрос следующий: при серередине у меня через goto label должно выкидывать из программы Auto, а получаеться что при выкидывании я получаю доступ к другим клавишам (чего не было при роботе цикла), но цикл закручиваеться на "Середина досягнута", посоветуйте как я могу это исправить, спасибо
А вот результаты роботы програмы
Я сказал все как есть на самом деле, зачем мне лгать кому то, практика работы с ардуино у меня всего 1.5 года
1.5 года? - а код пишете так, словно в ардуине 1.5 месяца
Я сказал все как есть на самом деле, зачем мне лгать кому то, практика работы с ардуино у меня всего 1.5 года
1.5 года? - а код пишете так, словно в ардуине 1.5 месяца
Соглашусь с вами, но на ошибках учатся, покажите мне пожалуйста где я написал коряво, или где можно было написать пограмотнее