Совет бывалых или как подключить два дальномера

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
День добрый.
Имеем такой проект. Сразу помидорами не кидайтесь - делали с учеником (даже ученицей). Это устройство, которое имеет реле для включения/выключения света в кабинете робототехники. Управляется ардуино уно. Идея была такой: в дверном косяке два сонара, которые отслеживают входит чел или выходит. Дублирующим на стене висит датчик движения. Воткнули туда плеер, фоторезистор, ИК-датчик, часы реального времени, датчик температуры. Человек входит, система его приветствует и включает свет, выходит - все наоборот. Ну, а дальше умность типа считает количество людей в кабинете, поэтому свет не выключается, если в кабинете люди типа есть. Долго никто не движется, система спрашивает и в случае отсутствия реакции свет выключает (на случай, если и правда никого нет). Становится слишком светло, выключает свет, темнеет, включает, все можно корректировать с пультика. Есть часы, в 22.00 система переходит в ночной режим (гасит свет, отключает сонары, работает только датчик движения, пошевелился - орет что Вы тут делаете, сейчас ночь, вызову сторожа), утром включается. Из плюшек - говорит время, значения температуры в кабинете и т.д. Залипательно все.

IMG_20231223_075152.jpg IMG_20231223_075208.jpg

Проект классный, но!
В результате эксплуатации выявили две проблемы:
1. Часы могут сбрасываться (питание отключалось или бывают сбои самого модуля часов) - решили поменять контроллер на wemos d1 r32 - тот же форм-фактор, ничего не надо будет переделывать, просто воткнем новый контроллер и будем брать время с инета или с локальной сети.
2. Сонары, блин, постоянно ошибаются. всячески их располагали, все-равно сбоят. Есть подозрение, что это не решаемая задача, тем более, что косяк кривой, то ли ультразвук как-то по-разному преломляется, да и человек входит в разных ракурсах, то боком, то прямо, да и люди все разные, разная одежда, видимо сонары перехватывают ультразвук друг друга, короче, не работает, как нам надо - решение заменить сонары на лазерные дальномеры.

И тут проблема. Я не смог ни сам подружить два дальномера на одном контроллере, ни найти об этом что либо в инете. Нашел про то, что можно подключать к А4 А5 несколько устройств, в примере был экран и модуль часов и типо они работают вместе. Подключал оба дальномера параллельно, они работают, но дублируют друг друга, читал их адреса, там один адрес 0х29, то есть они воспринимаются UART как одно устройство.

И собственно вопрос Чернышевского - что делать? Может один сонар, второй дальномер? Или взять дальномеры разной модификации? Или, вообще, не дальномеры? Или подскажете другой сопособ определения входа/выхода в проеме двери?
Подмогните с апргрейдом, с идеями.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,723
481
Подключал оба дальномера параллельно, они работают, но дублируют друг друга, читал их адреса, там один адрес 0х29, то есть они воспринимаются UART как одно устройство.
Так адреса должны быть разными. На платах дальномеров должны быть перемычки/резисторы для задания адреса конкретного устройства на шине I2C. Нужно смотреть на плату, а лучше в даташит. И да, не путайте UART и I2C.
 

rkit

★★★✩✩✩✩
5 Фев 2021
484
116
Не используй дальномеры для надежного обнаружения людей. Это просто не работает. Проще всего пир датчики движения.
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Дальномеры нужны для определения прохождения кого-либо в проеме двери, а два их, чтобы понять направление прохода. Датчик движения тут не поможет.

@PiratFox, и где тут перемычка?
1703312790440.png
Я запускал скейтч определения адреса устройств, в этот момент параллельно были подключены в I2C оба дальномера. Мне показало, что устройство одно и адрес его 0х29
 

Сотнег

★★★★★★★
15 Янв 2020
4,168
1,455
@Alexs-vplicei,
может, вам вместо двух неких датчиков взять одну линейку фоторезисторов?
Типа TLS1401.

А сонары не будут конфликтовать, если опрашивать их в разное время.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,723
481
@Alexs-vplicei, паршивое качество фото... Похоже, где обведено прямоугольником. А вообще, камрад @rkit прав: не нужен вам никакой дальномер. Достаточно оптических датчиков пересечения.
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
@PiratFox,
1703313290856.png

@Сотнег,
TLS1401 - это дороговато.

Сонары опрашиваются друг за другом. Но там надо это делать очень рядом, потому что расстояние между ними не большое. Мы их пробовали ставить на одной линии, потом разнесли по высоте. Но все-равно они глючат.

@PiratFox,
А это что такое "оптических датчиков пересечения"
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,877
600
44
Alexs-vplicei, надеюсь, вы уз-датчики не одновременно, а через определённую задержку опрашиваете?
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Оформи код соответствующим тэгом
@Геннадий П,
opros1();
opros2();

void opros1(){
digitalWrite(trig1,HIGH);
delay(5);
digitalWrite(trig1,LOW);
s1 = pulseIn(echo1,HIGH);
sm1 = abs((s1/2)/29.1); //Ближний (у кабинета)
}

void opros2(){
digitalWrite(trig2,HIGH);
delay(5);
digitalWrite(trig2,LOW);
s2 = pulseIn(echo2,HIGH);
sm2 = abs((s2/2)/29.1); //Дальний (у коридора)
}

Ну то есть это возможно получать данные от двух дальномеров по одному I2C? Просто в инете НИЧЕГО нет по этому поводу. Вот попробуйте найдите.
Мой поисковой запрос "подключение двух лазерных дальномеров" не дает никакой инфы поэтому поводу.

@Геннадий П,у меня есть подозрения, что датчики работают нормально. Просто в определенной позиции человек так отражает волну ультразвука, что она принимается и вторым датчиком.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,723
481
@Alexs-vplicei, я же говорю, нужен даташит на ваше устройство, чего гадать на кофейной гуще. Можно, например, по маркировке чипа поискать.
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Я тогда и возьму VL53L0X.
У меня сейчас VL6180X, а он дальше 25 см. не видит.
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
@rkit,еще стоять в проеме двери.
Я как раз рассматривал дальномеры в качестве датчиков пересечения.
А вопросы махания рук можно дублировать датчиком движения, прошел, значит датчик сработал. Не прошал, на датчике тишина. И также выход. Важно, чтобы срабатывания пересечения были четкие. По очередности срабатывания и определяется направление.

@Геннадий П,Да,вспомнил еще один момент. Сонары плохо срабатывали, если пройти быстро. Поэтому и минимизировали опрос датчиков между собой.
 

varankz

✩✩✩✩✩✩✩
15 Апр 2022
1
0
Доброе время суток. Столкнулись с похожей проблемой в проекте робота сумо. Было принято решение использовать I2C мультиплексор TCA9548A. Код сырой прошу не судить строго, но работает. :)
Код:
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
#define TCAADDR 0x70
#define HIGH_SPEED
int mm1;

void tcaselect(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission(); 
}
void setup() {
    Serial.begin(9600);
    Wire.begin();
    tcaselect(0);
    sen();
    delay(10);
    tcaselect(6);
    sen();
    delay(10);
}

void loop() {
    tcaselect(0);
     mm1 = sensor.readRangeSingleMillimeters();
     Serial.print("port 0= ");
     Serial.print(mm1);
     delay(20);

     tcaselect(6);
     mm1 = sensor.readRangeSingleMillimeters();
     Serial.print("port 6= ");
     Serial.println(mm1);
}

void sen() {
    sensor.setTimeout(50);
    sensor.setSignalRateLimit(0.7);
    sensor.init();
}
 

Вложения

Изменено:

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Нашел библиотеку, где в примере есть работа двух датчиков!!! Там используется SHUT датчика.
Загрузил пример, подключил как написано и все заработало. Судя по проге используются адреса 0х30 и 0х31. Обрадовался. Но не долго музыка играла. Подключил к I2C дисплей. И вроде адрес у него 0х27, а работать перестало. А почему? Вот вопрос. Помогайте.

Вот код из примера куда я добавил дисплей. Я пока закоментил то, что ломает прогу. Работаю с Уно.

C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#include "Adafruit_VL53L0X.h"
// address we will assign if dual sensor is present
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31
// set the pins to shutdown
#define SHT_LOX1 7
#define SHT_LOX2 6
// objects for the vl53l0x
Adafruit_VL53L0X lox1 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox2 = Adafruit_VL53L0X();
// this holds the measurement
VL53L0X_RangingMeasurementData_t measure1;
VL53L0X_RangingMeasurementData_t measure2;

#define led1 11
#define led2 12

void setID() {
  // all reset
  digitalWrite(SHT_LOX1, LOW);   
  digitalWrite(SHT_LOX2, LOW);
  delay(10);
  // all unreset
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);
  // activating LOX1 and resetting LOX2
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, LOW);
  // initing LOX1
  if(!lox1.begin(LOX1_ADDRESS)) {
    Serial.println(F("Failed to boot first VL53L0X"));
    while(1);
  }
  delay(10);
  // activating LOX2
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);
  //initing LOX2
  if(!lox2.begin(LOX2_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  }
}

void read_dual_sensors() {
  lox1.rangingTest(&measure1, false); // pass in 'true' to get debug data printout!
  lox2.rangingTest(&measure2, false); // pass in 'true' to get debug data printout!
  // print sensor one reading
  Serial.print(F("1: "));
  if(measure1.RangeStatus != 4) {     // if not out of range
    Serial.print(measure1.RangeMilliMeter);
  } else {
    Serial.print(F("Out of range"));
  }
  Serial.print(F(" "));
  // print sensor two reading
  Serial.print(F("2: "));
  if(measure2.RangeStatus != 4) {
    Serial.print(measure2.RangeMilliMeter);
  } else {
    Serial.print(F("Out of range"));
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);
//  lcd.init();                      // тут ломается
//  lcd.backlight();

// wait until serial port opens for native USB devices
   while (! Serial) { delay(1); }
    pinMode(SHT_LOX1, OUTPUT);
    pinMode(SHT_LOX2, OUTPUT);

  Serial.println(F("Shutdown pins inited..."));
  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);

  Serial.println(F("Both in reset mode...(pins are low)"));
  Serial.println(F("Starting..."));
  setID();
}

void loop() {
  read_dual_sensors();
//  lcd.setCursor(1,0);
//  lcd.print("Hello, world!");
  delay(100);
}
 

Вложения

Изменено:

vortigont

★★★★★★✩
24 Апр 2020
941
507
Saint-Petersburg, Russia
во-первых: уберике код под соответсвующий тег что бы он был читаем.

вроде адрес у него 0х27
Во-вторых: вы же попробовали отдельно экран без датчиков запустить, да? Выводить на него данные, обновлять?
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Gfhljy @vortigont, Пардон, поправил. Конечно пробовал. По отдельности все работает, вместе контроллер постоянно перезапускается.

@vortigont,даже больше. Я пробовал оставлять один датчик. В этом случае экран работает.
C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display


#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.setCursor(1,1);
  lcd.print("-------------");
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }
 
  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power
  Serial.println(F("VL53L0X API Simple Ranging example\n\n"));
}


void loop() {
  VL53L0X_RangingMeasurementData_t measure;
    
  Serial.print("Reading a measurement... ");
  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

  if (measure.RangeStatus != 4) {  // phase failures have incorrect data
    Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
  } else {
    Serial.println(" out of range ");
  }
  lcd.setCursor(1,0);
  lcd.print("Hello"); 
  delay(100);
}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
Самое первое что надо сделать - запустить сканер I2C , проверить как видны эти устройства.
Второе , что бы я сделал, взял бы мультиметр и на всех i2c устройствах, отключенных от всего, прозвонил бы контакты + и SDA, + и SCL , стандартно эти линии подтягиваются к + резистором на 4.6 - 10 кОм, но такая подтяжка должна быть только одна на всей линии. Если подтяжка есть на каждом устройстве, то это может быть причиной отказа.
 
  • Лойс +1
Реакции: rv1cj

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
@Старик Похабыч,А почему тогда с одним датчиком дисплей работает, а с двумя нет. Если бы проблема была в подтягивании резистором, то это бы привело к отказу и с одним дальномером.

@Старик Похабыч,и если так, то как производители устройств предполагают, что надо на каждом из них убирать подтягивающий резистр, а потом делать один общий? А ведь заявленно, к I2С можно подключить аж до 128 устройств!
 

Alexs-vplicei

✩✩✩✩✩✩✩
18 Авг 2021
52
3
Вот сейчас тестю такую программу.
В сетапе экран включается, на нем пишется, что надо. Потом идет опрос датчиков. Они работают, но как только я пытяюсь сделать вывод на дисплей ардуино просто перезагружается. Вообще не понимаю почему?


C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#include "Adafruit_VL53L0X.h"

// address we will assign if dual sensor is present
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31

// set the pins to shutdown
#define SHT_LOX1 6
#define SHT_LOX2 7

// objects for the vl53l0x
Adafruit_VL53L0X lox1 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox2 = Adafruit_VL53L0X();

// this holds the measurement
VL53L0X_RangingMeasurementData_t measure1;
VL53L0X_RangingMeasurementData_t measure2;

#define led1 11
#define led2 12
int sm1=0,sm2=0;
String sos="";
bool mask1=true,mask2=true;

void setID() {
  // all reset
  digitalWrite(SHT_LOX1, LOW);   
  digitalWrite(SHT_LOX2, LOW);
  delay(10);
  // all unreset
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);
  // activating LOX1 and resetting LOX2
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, LOW);
  // initing LOX1
  if(!lox1.begin(LOX1_ADDRESS)) {
    Serial.println(F("Failed to boot first VL53L0X"));
    while(1);
  }
  delay(10);
  // activating LOX2
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);
  //initing LOX2
  if(!lox2.begin(LOX2_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  }
}

void read_dual_sensors() { 
  lox1.rangingTest(&measure1, false); // pass in 'true' to get debug data printout!
  lox2.rangingTest(&measure2, false); // pass in 'true' to get debug data printout!
  // print sensor one reading
  Serial.print(F("1: "));
  if(measure1.RangeStatus != 4) {     // if not out of range
    sm1=measure1.RangeMilliMeter;
    Serial.print(sm1);
  } else {
    Serial.print(F("Out of range"));
    sm1=1500;}
 
  Serial.print(F(" "));
  // print sensor two reading
  Serial.print(F("2: "));
  if(measure2.RangeStatus != 4) {
    sm2=measure2.RangeMilliMeter;
    Serial.print(sm2);
  } else {
    Serial.print(F("Out of range"));
    sm2=1500;  } 
  Serial.println();
}

void setup() {
  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.setCursor(1,1);
  lcd.print("-------------");
  Serial.begin(115200);
  // wait until serial port opens for native USB devices
  while (! Serial) { delay(1); }

  pinMode(SHT_LOX1, OUTPUT);
  pinMode(SHT_LOX2, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  Serial.println(F("Shutdown pins inited..."));
  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);
  Serial.println(F("Both in reset mode...(pins are low)"));   
  Serial.println(F("Starting..."));
  setID();
}

void loop() {
  
  read_dual_sensors();
  if (sm1<1000 and mask1) {sos+='1';mask1=false;}
  if (sm2<1000 and mask2) {sos+='2';mask2=false;}
  if (sos=="12") {digitalWrite(led1,1);digitalWrite(led2,0);mask1=true;mask2=true;sos="";
  lcd.setCursor(1,0);
  lcd.print("EXIT            "); //вот здесь все ломается
  }
  if (sos=="21") {digitalWrite(led1,0);digitalWrite(led2,1);mask1=true;mask2=true;sos="";
//  lcd.setCursor(1,0);
//  lcd.print("ENTRANCE        ");
  }
 
  delay(25);
}
Вот что пишется в мониторе порта. То есть контроллер конкретно перезагружается

1: 148 2: 350
1: 147 2: 354
Shutdown pins inited...
Both in reset mode...(pins are low)
Starting...
1: Out of range 2: 288
1: Out of range 2: 287
1: Out of range 2: 295
1: Out of range 2: 293
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
Есть такая наука, физика, Если линия подтянута одним сопротивлением в 4,6 кОм, то так она и будет. а если 3-мя, то результирующее сопротивление будет в 3 раза меньше, т.к. параллельно стоят 3 сопротивления и что там в конце концов будет не понятно.
Производитель не обязан думать за других производителей, и за Вас тоже, он считает, что те, кто будет использовать его модуль человек грамотный, и понимает, что 8-ой вагон это тот который после 7-го, а не тот , который перед 9-ым
Если при подключенных всех модулях код отдельно на дисплей и отдельно на датчики работает нормально, то скорее всего дело не в сопротивлении.

Вы сам то код хорошо изучили ? Для чего вот это:

C++:
  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
340
105
@Alexs-vplicei,
Если у вас есть 2560, то попробуйте на ней. Так вы проверите возможную нехватку памяти.