VL53L0X и несколько ардуин

Buran
Offline
Зарегистрирован: 04.11.2019

Всем привет! Столкнулся вот с такой проблемкой. У меня есть несколько датчиков VL53L0X (6) на шине I2C. На этой же шине две ардуины одна задает всем датчикам новые адреса вот таким способом:

  digitalWrite(PR_BACKSIDE, HIGH);
  delay(150);
  prep_backside.init(true);
  delay(100);
  prep_backside.setAddress((uint8_t)27);
  
  digitalWrite(PR_RIGHT, HIGH);
  delay(150);
  prep_right.init(true);
  delay(100);
  prep_right.setAddress((uint8_t)25);

Вторая ардуина должна прочитать значения с новых адресов этих датчиков. Проблема в том, что вторая ардуина не инициализирует эти новые адреса и я не могу найти в библиотеке (VL53L0X) как обратиться к датчику по адресу. Может есть у какого какие предположения как это можно сделать?

nik182
Offline
Зарегистрирован: 04.05.2015

Простите, а какие адреса имеются в виду? У датчика только один адрес и его изменить нельзя Вот кусок мануала:and uses a device address of 0x52.

Logik
Offline
Зарегистрирован: 05.08.2014

И тем не менее есть.

/* Group PAL Init Functions */
VL53L0X_Error VL53L0X_SetDeviceAddress(VL53L0X_DEV Dev, uint8_t DeviceAddress)
{
	VL53L0X_Error Status = VL53L0X_ERROR_NONE;
	LOG_FUNCTION_START("");

	Status = VL53L0X_WrByte(Dev, VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS,
		DeviceAddress / 2);

	LOG_FUNCTION_END(Status);
	return Status;
}

 

и 

/**************************************************************************/
/*! 
    @brief  Change the I2C address of the sensor
    @param  newAddr the new address to set the sensor to
    @returns True if address was set successfully, False otherwise
*/
/**************************************************************************/
boolean Adafruit_VL53L0X::setAddress(uint8_t newAddr) {
  newAddr &= 0x7F;

  Status = VL53L0X_SetDeviceAddress(pMyDevice, newAddr * 2); // 7->8 bit

  delay(10);

  if( Status == VL53L0X_ERROR_NONE ) {
    pMyDevice->I2cDevAddr = newAddr;  // 7 bit addr
    return true;
  }
  return false;
}

и даже вызывается из  Adafruit_VL53L0X::begin(

  Status = VL53L0X_DataInit( &MyDevice );         // Data initialization

  if (! setAddress(i2c_addr) ) {
    return false;
  }

  Status = VL53L0X_GetDeviceInfo( &MyDevice, &DeviceInfo );

 

Зачем не знаю.

Buran
Offline
Зарегистрирован: 04.11.2019

Как раз таки адреса менять можно при помощи контакта "XSHUT". Иначе какой смысл их использовать на шине, если нельзя поменять адрес. Тем более Вы утверждаете обратное тому, что я уже сделал. У меня ардуина раздала адреса каждому датчику и внимательно каждого слушает по новым адресам, проблема возникла как сделать, чтобы слушала их другая ардуина.

b707
Offline
Зарегистрирован: 26.05.2017

Buran пишет:

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

вижу два варианта - более аккуратный - дописать в библиотеку инициализацию с указанием адреса

и более топорный метод - еще раз назначить датчикам те же самые адреса, только уже с другой ардуины.

Logik
Offline
Зарегистрирован: 05.08.2014

Инициализация там и так с адресом, он просто по умолчанию задан. Вот мужики и не знают то!

class Adafruit_VL53L0X
{
  public:
    boolean       begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false ); 

Вопросов вообще 2.

1. А оно вообще работает, эта смена адреса? Может так приблудилась ;)

2. А нахрена оно надо? Если у меня 10 датчиков изначально на шине на одном адресе VL53L0X_I2C_ADDR, то что толку, кому я чего поменяю. Может конечно смена адреса сохраняется после выключения, но непохоже.

 

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Нашёл UM2039. User API. Вот только не понял как поменять изначальный адрес если на шине висит несколько штук. По одному менять, потом на шину вешать? Функция есть. Описания нет. 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Разобрался. Новый адрес можно запрограммировать только один раз сразу после ресета. 

То есть каждый датчик должен для этого иметь оттдельно подключенный XSHUT. 

Дальше датчики по одному выводятся из ресета и им по очереди назначается адрес.

sadman41
Offline
Зарегистрирован: 19.10.2016

nik182 пишет:

Да. Нашёл UM2039. User API. Вот только не понял как поменять изначальный адрес если на шине висит несколько штук. По одному менять, потом на шину вешать? Функция есть. Описания нет. 

For future reference, the default I2C address is 0x29. You can change it, but only in software. That means you have to wire the SHUTDOWN pin and hold all but one sensor in reset while you reconfigure one sensor at a time.

https://cdn-learn.adafruit.com/downloads/pdf/adafruit-vl53l0x-micro-lidar-distance-sensor-breakout.pdf

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Что бы работать с уже проинициализированными другой ардуиной датчиками можно подправить библиотеку и в методе

Adafruit_VL53L0X::beginAdafruit_VL53L0X::begin()

не вызывать 

setAddress()

Logik
Offline
Зарегистрирован: 05.08.2014

Получается на каждый датчик свою линию XSHUT. Ну такое еще решение. Хотя возможно GPIO1 для этого, типа цепочкой GPIO1 одного к XSHUT следующего.  Надо смотреть состояние  GPIO1  по ресету.

Logik
Offline
Зарегистрирован: 05.08.2014

asam пишет:

Что бы работать с уже проинициализированными другой ардуиной датчиками можно подправить библиотеку и в методе

Adafruit_VL53L0X::beginAdafruit_VL53L0X::begin()

не вызывать 

setAddress()

Просто в "другой" вызывать begin() с адресом, выданным "первой".

Logik
Offline
Зарегистрирован: 05.08.2014

На таких 

Картинки по запросу VL53L0X

нет  GPIO1 и XSHUT. Зато есть 2 неподписанные дырки. Это они?

b707
Offline
Зарегистрирован: 26.05.2017

asam пишет:

Что бы работать с уже проинициализированными другой ардуиной датчиками можно подправить библиотеку....

Logik пишет:

Просто в "другой" вызывать begin() с адресом, выданным "первой".

в итоге пришли к двум моим вариантам из сообщения #4 :))

- это так, к слову :)

Logik
Offline
Зарегистрирован: 05.08.2014

Эти шоле?

b707 пишет:

 

вижу два варианта - более аккуратный - дописать в библиотеку инициализацию с указанием адреса

и более топорный метод - еще раз назначить датчикам те же самые адреса, только уже с другой ардуины.

Да причем оно, тем более что "инициализацию с указанием адреса"  - имеем в либке изначально. Но если Вам приятно, то пускай ;)

Дело в том что адрес в бегин нужен для того, чтоб: 1.сменить адрес устройства на i2c записав в него этот самый адрес и 2. работать с датчиком на указанном адресе. Но беда что п.2 выполняется только при успешном п.1 Эта проверка см. #2 Adafruit_VL53L0X::setAddress стр.15 . Она получается для второй ардуины все портит т.к. сменить уже не получится. Значить и как #11 не отработает (( , если не убрать нахрен эту проверку. Тогда получится что бегин пытается сменить адрес и независимо от успешности будет пытатся работать по этому адресу. Пожалуй так.

 

nik182
Offline
Зарегистрирован: 04.05.2015

sadman41 пишет:

nik182 пишет:

Да. Нашёл UM2039. User API. Вот только не понял как поменять изначальный адрес если на шине висит несколько штук. По одному менять, потом на шину вешать? Функция есть. Описания нет. 

For future reference, the default I2C address is 0x29. You can change it, but only in software. That means you have to wire the SHUTDOWN pin and hold all but one sensor in reset while you reconfigure one sensor at a time.

https://cdn-learn.adafruit.com/downloads/pdf/adafruit-vl53l0x-micro-lidar-distance-sensor-breakout.pdf

Это я тоже нашёл. Как и шилд под три датчика со схемой. https://www.st.com/content/ccc/resource/technical/document/user_manual/group0/b4/df/b1/37/b3/a9/46/b6/DM00285104/files/DM00285104.pdf/jcr:content/translations/en.DM00285104.pdf

ХSHUNTы идут на каждый чип свой вот только через согласователь уровня нна 2.8 вольта . И в #0 стали понятны строки 1 и 7.  Вот только в описании API  https://www.st.com/content/ccc/resource/technical/document/user_manual/group0/6b/4e/24/90/d8/05/47/a5/DM00279088/files/DM00279088.pdf/jcr:content/translations/en.DM00279088.pdf нет команды получения текущего адреса. Так что ни кто, даже инициатор замены прочитать на что заменил не сможет. Нужно помнить и передавать другим нуждающимся. Ну или дергать ХSHUNTы и i2c сканером читать те которые появились после дёргания. Если конечно у второй доступ к ХSHUNTам есть. 

Logik
Offline
Зарегистрирован: 05.08.2014

//нет команды получения текущего адреса. 

))) разумеется нет! Чтоб получить адрес от датчика надо обратится к датчику по этому адресу!

Но для ТС это не проблема, задал одинаковой константой двум ардуинам и все.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Logik пишет:

asam пишет:

Что бы работать с уже проинициализированными другой ардуиной датчиками можно подправить библиотеку и в методе

Adafruit_VL53L0X::beginAdafruit_VL53L0X::begin()

не вызывать 

setAddress()

Просто в "другой" вызывать begin() с адресом, выданным "первой".

 

Если так сделать, то на второй ардуине Adafruit_VL53L0X::begin вывалится на середине с ошибкой не завершив инициализацию. Поскольку она уже прошла, то может и будет все равно работать. А может и нет. Надо попробовать, а у меня такого датчика нет.

Logik
Offline
Зарегистрирован: 05.08.2014

Так пишу же "не отработает (( , если не убрать нахрен эту проверку". Скорей всего так, вывалится.

ТС попробует. Оно же ему надо.

Если че не срастется - я могу пробовать, у меня этот гад подключен прямо сейчас.

Buran
Offline
Зарегистрирован: 04.11.2019

b707 пишет:

Buran пишет:

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

вижу два варианта - более аккуратный - дописать в библиотеку инициализацию с указанием адреса

и более топорный метод - еще раз назначить датчикам те же самые адреса, только уже с другой ардуины.

пробовал топорный вариант, не получилось. Возможно, из-за того, что вторая ардуина  подключена к датчикам только по I2C и нет возможности подключить "XSHUT"

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А может дело не в датчике , а в двух ардуинах? Ты не пробовал читать один какой нибудь датчик с фиксированным адресом с двух ардуин

Buran
Offline
Зарегистрирован: 04.11.2019

asam пишет:

А может дело не в датчике , а в двух ардуинах? Ты не пробовал читать один какой нибудь датчик с фиксированным адресом с двух ардуин

Я же писал, что первая ардуина читает все с новыми адресами. Со второй ардуиной все в порядке и шина у нее рабочая

Logik
Offline
Зарегистрирован: 05.08.2014

При сборке для второй ардуины закоментируй проверку из #14. Без этого она не пререйдет на новый адрес.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Buran пишет:

asam пишет:

А может дело не в датчике , а в двух ардуинах? Ты не пробовал читать один какой нибудь датчик с фиксированным адресом с двух ардуин

Я же писал, что первая ардуина читает все с новыми адресами. Со второй ардуиной все в порядке и шина у нее рабочая

 

Я же писал, что попробуйте какой нибудь другой датчик с фиксированным адресом. То что вторая ардуина в порядке я не сомневаюсь. Но когда 2 ардуины находятся на одной шине и обращаются к одному и тому же i2c слейву, могут возникать проблемы.

Deamount
Offline
Зарегистрирован: 07.05.2012

Здравствуйте. меня серьёзно обломал данные сенсор тем, что адрес нельзя записать навсегда. 

я ещё спалил уже две штуки. нужна помощь. пример взял здесь https://robojax.com/learn/arduino/?vid=robojax_VL53L0X_multiple

6,7 ноги управляют выводами xshut. 
во всех инструкциях пишут подать high для ресета и т.д. но там короткое замыкание! плата моментально нагревается и видимо выходит из строя, т.к. потом не определяется. перестаёт появляться в поиске на шине i2c

подскажите правильный метод установки адреса. в чём может быть дело? (может модули с китайской помойки?)

#include "Adafruit_VL53L0X.h"

// address we will assign if dual sensor is present
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31
int sensor1,sensor2;


// 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;

/*
    Reset all sensors by setting all of their XSHUT pins low for delay(10), then set all XSHUT high to bring out of reset
    Keep sensor #1 awake by keeping XSHUT pin high
    Put all other sensors into shutdown by pulling XSHUT pins low
    Initialize sensor #1 with lox.begin(new_i2c_address) Pick any number but 0x29 and it must be under 0x7F. Going with 0x30 to 0x3F is probably OK.
    Keep sensor #1 awake, and now bring sensor #2 out of reset by setting its XSHUT pin high.
    Initialize sensor #2 with lox.begin(new_i2c_address) Pick any number but 0x29 and whatever you set the first sensor to
 */
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 reseting 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("1: ");
  if(measure1.RangeStatus != 4) {     // if not out of range
    sensor1 = measure1.RangeMilliMeter;    
    Serial.print(sensor1);
    Serial.print("mm");    
  } else {
    Serial.print("Out of range");
  }
  
  Serial.print(" ");

  // print sensor two reading
  Serial.print("2: ");
  if(measure2.RangeStatus != 4) {
    sensor2 = measure2.RangeMilliMeter;
    Serial.print(sensor2);
    Serial.print("mm");
  } else {
    Serial.print("Out of range");
  }
  
  Serial.println();
}

void setup() {
  Serial.begin(115200);

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

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

  Serial.println("Shutdown pins inited...");

  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);

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

void loop() {
   
  read_dual_sensors();
  delay(100);
}
 

 

Thest
Offline
Зарегистрирован: 24.11.2015

Deamount пишет:

Здравствуйте. меня серьёзно обломал данные сенсор тем, что адрес нельзя записать навсегда.

я ещё спалил уже две штуки. нужна помощь. пример взял здесь https://robojax.com/learn/arduino/?vid=robojax_VL53L0X_multiple

6,7 ноги управляют выводами xshut.
во всех инструкциях пишут подать high для ресета и т.д. но там короткое замыкание! плата моментально нагревается и видимо выходит из строя, т.к. потом не определяется. перестаёт появляться в поиске на шине i2c

подскажите правильный метод установки адреса. в чём может быть дело? (может модули с китайской помойки?)

Скачай библиотеку Adafruit_VL53L0X, у неё есть пример с подключением двух сенсоров.

Спалил ты их, потому, что gpio и xshut не имеют логического преобразователя напряжения, датчик питается от 2.8 вольт, а ты подал 5 на них. VCC, SDA, SCL идут через преобразователь, они 5.5 вольт выдерживают.

Тут очень хорошо описали датчик, и дают ссылки на литературу по нему https://robototehnika.ru/e-store/catalog/409/2251/ 

UPD:
хотя код у тебя их, только немного изменён. Попробуй именно пример их библиотеки. У меня работает отлично, может конечно у меня плата со стабилизатором, хотя я его в упор не вижу