Как считать адреса на нескольких платах DS2413 1-Wire GPIO, используя скетч Adafruit?

Я использую три DS2413 1-Wire GPIO Breakouts от Adafruit, подключенные к ESP8266. Я протестировал DS2413 breakouts, используя их пример скетча, и он отлично работает только для одного DS2413. Но я не могу заставить его работать, когда подключены 2 или более DS2413.

Пример скетча Adafruit DS2413 https://github.com/adafruit/Adafruit_DS2413/blob/master/DS2413.pde

Обзор Adafruit DS2413
https://learn.adafruit.com/adafruit-1-wire-gpio-breakout-ds2413?view=all

Когда я подключаю 2 или более DS2413, мигают только светодиоды, подключенные к 1-му разъему, и не считываются другие адреса.

Я внес некоторые изменения в раздел void setup, и теперь я получаю следующее в последовательном мониторе. Он видит все адреса, но дублирует их, и в первом наборе в конце есть "No device found on the bus!". Как мне заставить скетч считывать все адреса без этих ошибок?

Последовательный монитор

Looking for a DS2413 on the bus
3A B2 C2 39 00 00 00 8C No device found on the bus!
3A 8E AE 39 00 00 00 2C No device found on the bus!
3A E5 B6 39 00 00 00 55 No device found on the bus!
Found a DS2413: 3A B2 C2 39 00 00 00 8C 
Found a DS2413: 3A 8E AE 39 00 00 00 2C 
Found a DS2413: 3A E5 B6 39 00 00 00 55

Вот код с моими изменениями.

#include <OneWire.h>

#define DS2413_ONEWIRE_PIN  (4)

#define DS2413_FAMILY_ID    0x3A
#define DS2413_ACCESS_READ  0xF5
#define DS2413_ACCESS_WRITE 0x5A
#define DS2413_ACK_SUCCESS  0xAA
#define DS2413_ACK_ERROR    0xFF

OneWire oneWire(DS2413_ONEWIRE_PIN);
uint8_t address[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

void printBytes(uint8_t* addr, uint8_t count, bool newline=0) 
{
  for (uint8_t i = 0; i < count; i++) 
  {
    Serial.print(addr[i]>>4, HEX);
    Serial.print(addr[i]&0x0f, HEX);
    Serial.print(" ");
  }
  if (newline)
  {
    Serial.println();
  }
}

byte read(void)
{      
  bool ok = false;
  uint8_t results;

  oneWire.reset();
  oneWire.select(address);
  oneWire.write(DS2413_ACCESS_READ);

  results = oneWire.read();                 /* Get the register results   */
  ok = (!results & 0x0F) == (results >> 4); /* Compare nibbles            */
  results &= 0x0F;                          /* Clear inverted values      */

  oneWire.reset();

  // return ok ? results : -1;
  return results;
}

bool write(uint8_t state)
{
  uint8_t ack = 0;

  /* Top six bits must '1' */
  state |= 0xFC;

  oneWire.reset();
  oneWire.select(address);
  oneWire.write(DS2413_ACCESS_WRITE);
  oneWire.write(state);
  oneWire.write(~state);                    /* Invert data and resend     */    
  ack = oneWire.read();                     /* 0xAA=success, 0xFF=failure */  
  if (ack == DS2413_ACK_SUCCESS)
  {
    oneWire.read();                          /* Read the status byte      */
  }
  oneWire.reset();

  return (ack == DS2413_ACK_SUCCESS ? true : false);
}

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

  Serial.println(F("Looking for a DS2413 on the bus"));

  /* Try to find a device on the bus */
  oneWire.reset_search();
  delay(250);
  while (oneWire.search(address)) {
       printBytes(address, 8);
       Serial.println(F("No device found on the bus!"));
} 
  /* Check the CRC in the device address */
  if (OneWire::crc8(address, 7) != address[7]) 
  {
    Serial.println(F("Invalid CRC!"));
    return;
  }

  /* Make sure we have a DS2413 */
  if (address[0] != DS2413_FAMILY_ID) 
  {
    printBytes(address, 8);
    Serial.println(F(" is not a DS2413!"));
    return;
  }

  while (oneWire.search(address)) {
  Serial.print(F("Found a DS2413: "));
  printBytes(address, 8);
  Serial.println(F(""));
}
}

void loop(void) 
{
  /* Read */
  /*
  uint8_t state = read();
  if (state == -1)
    Serial.println(F("Failed reading the DS2413"));
  else
    Serial.println(state, BIN);
  */

  /* Write */
  bool ok = false;
  ok = write(0x3);
  if (!ok) Serial.println(F("Wire failed"));
  delay(1000);
  ok = write(0x0);
  if (!ok) Serial.println(F("Wire failed"));
  delay(1000);
}

, 👍0


2 ответа


Лучший ответ:

0

Мне удалось заставить ESP8266 считывать все устройства DS2413 без ошибок, а также мигать каждым светодиодом, подключенным к DS2413, по отдельности, по всей цепочке.

Вот анимация того, как это работает. multiple_DS2413_blink multiple_DS2413_read

Я полностью благодарен mortonkopf на Github. Его скетч DS2413_button_array_test был именно тем, что мне было нужно, чтобы иметь возможность считывать адреса на всех подключенных устройствах DS2413 и мигать каждым светодиодом. Вот ссылка на его репозиторий OneWire_DS2413_array.

https://github.com/mortonkopf/OneWire_DS2413_array

Вот код, который я использую, чтобы это работало.

// Этот скетч основан на скетче DS2413_button_array_test от mortonkopf и позволяет
// вы можете считать данные с нескольких устройств DS2413 и мигать светодиодом, подключенным к каждому DS2413,
// индивидуально, по цепочке.
// https://github.com/mortonkopf/OneWire_DS2413_array
//
// Этот скетч представляет собой усовершенствованную функцию записи Adafruit DS2413
// скетч, который считывает только 1 устройство DS2413.
// https://github.com/adafruit/Adafruit_DS2413
// https://learn.adafruit.com/adafruit-1-wire-gpio-breakout-ds2413/reading-writing-and-arithmatic

#include <OneWire.h>

/* reading pins
0x0 (B00000000) - Both pins LOW
0x1 (B00000001) - IOA = HIGH, IOB = LOW
0x2 (B00000010) - IOA = LOW, IOB = HIGH
0x3 (B00000011) - Both pins HIGH
0xFF (B11111111) - Read Failed!
*/
#define DS2413_ONEWIRE_PIN  (4) // GPIO 4 на Adafruit Feather HUZZAH ESP8266

#define DS2413_FAMILY_ID    0x3A
#define DS2413_ACCESS_READ  0xF5
#define DS2413_ACCESS_WRITE 0x5A
#define DS2413_ACK_SUCCESS  0xAA
#define DS2413_ACK_ERROR    0xFF

#define BUTTON_NO 3 //используйте это для размера массива для хранения значений состояния//

OneWire oneWire(DS2413_ONEWIRE_PIN);
uint8_t address[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

byte Button_states[BUTTON_NO];//это массив состояний кнопок//

void printBytes(uint8_t* addr, uint8_t count, bool newline=0) 
{
  for (uint8_t i = 0; i < count; i++) 
  {
    Serial.print(addr[i]>>4, HEX);
    Serial.print(addr[i]&0x0f, HEX);
    Serial.print(" ");
  }
  if (newline)
  {
    Serial.println();
  }
}

byte read(void)
{ 
  bool ok = false;
  uint8_t results;

  oneWire.reset();
  oneWire.select(address);
  oneWire.write(DS2413_ACCESS_READ);

  results = oneWire.read();                 /* Get the register results   */
  ok = (!results & 0x0F) == (results >> 4); /* Compare nibbles            */
  results &= 0x0F;                          /* Clear inverted values      */

  oneWire.reset();

  // вернуть ok ? результаты : -1;
  return results;
}

bool write(uint8_t state)
{
  uint8_t ack = 0;

  /* Top six bits must '1' */
  state |= 0xFC;

  oneWire.reset();
  oneWire.select(address);
  oneWire.write(DS2413_ACCESS_WRITE);
  oneWire.write(state);
  oneWire.write(~state);                    /* Invert data and resend     */    
  ack = oneWire.read();                     /* 0xAA=success, 0xFF=failure */  
  if (ack == DS2413_ACK_SUCCESS)
  {
    oneWire.read();                          /* Read the status byte      */
  }
  oneWire.reset();

  return (ack == DS2413_ACK_SUCCESS ? true : false);
}

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

  Serial.println(F("Looking for a DS2413 on the bus"));
}

void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  if ( !oneWire.search(address)) {
    Serial.println("");
    Serial.print("No more addresses.\n");
    oneWire.reset_search();
    delay(50); //было 250
    return;
  }
  Serial.println("");
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(address[i], HEX);
    Serial.print(" ");
  }  

  if ( OneWire::crc8( address, 7) != address[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }

  if ( address[0] != DS2413_FAMILY_ID) {
      Serial.print("Device is not a DS2413 family device.\n");
      return;
  }

// Поочередно мигать каждым светодиодом, подключенным к DS2413
  bool ok = false;
  ok = write(0x1);
  if (!ok) Serial.println(F("Wire failed"));
  delay(200);
  ok = write(0x2);
  if (!ok) Serial.println(F("Wire failed"));
  delay(200);
  ok = write(0x0);
  if (!ok) Serial.println(F("Wire failed"));
  delay(200);
///////////////////

uint8_t state = read();
  const int IOA = 0x1;
  const int IOB = 0x2;

  if (state == -1)
  {
    Serial.println(F("Failed reading the DS2413"));
  }
  else
  {
    if (state & IOA)
    {
       Serial.print("   A");
    }
    if (state & IOB)
    { //можно использовать этот ввод-вывод при необходимости для выполнения задач
        Serial.print("   B");
    }
  }

}

Вот ссылка на Gist, который я создал для этого наброска. https://gist.github.com/orbitrod/51eb10c1a88f5747dc79298030e4480c

,

0

В вашей функции настройки есть два контура обнаружения. Его можно смело удалить, так как для каждого обнаруженного устройства будет выведено сообщение об ошибке.

while (oneWire.search(address)) {
   printBytes(address, 8);
   Serial.println(F("No device found on the bus!"));

}

,