Считать данные с DS2406

Romosyto
Offline
Зарегистрирован: 15.01.2014

Здравствуйте. Помогите пожалуйста разобраться с двухканальным 1-wire ключом DS2406P

Даташит взял тут http://pdfserv.maximintegrated.com/en/ds/DS2406.pdf.

Пробовал пользоваться библиотекой http://github.com/dustin/arduino-2406. Но среди ее стандартных функций не разобрался как настроить порт PIO_A на ввод и считать его состояние. В примерах есть только запись в память

В программировании еще новичок. Вот набросал код с использованием библиотеки OneWire

#include <OneWire.h>

OneWire ds(9);
uint8_t address[8] = {0x12, 0x2E, 0xED, 0x3D, 0, 0, 0, 0xC7};
uint8_t CHANNEL_ACCESS = 0xF5;
uint8_t CHANNEL_CONTROL_BYTE = 01000100; //ALR=0;IM=1;TOG=0;IC=0;CHS1=0;CHS0=1;CRC1=0;CRC0=0
uint8_t buffer;

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

void loop(void)
{
ds.reset();
ds.select(address);
ds.write(CHANNEL_ACCESS,1);
ds.write(CHANNEL_CONTROL_BYTE,1);
ds.write(0xFF,1);
ds.write(CHANNEL_CONTROL_BYTE,1);
ds.write(0xFF,1);
buffer = ds.read();
ds.reset();
Serial.println(buffer);
delay(2000);
}

Но в мониторе порта постоянно показывает 255 (11111111). Чего по идее (согласно даташиту) не должно быть.

Помогите разобраться пожалуйста. Спасибо.

 

NE_XT
NE_XT аватар
Offline
Зарегистрирован: 22.05.2012

В свое время руки не дошли научиться читать, вот списочек  может вам поможет.

ds.write(0x33); // Read ROM 
ds.write(0x55); // Match ROM 
ds.write(0xCC); // Skip ROM 
ds.write(0x0F); // Search ROM 
ds.write(0x4E); // Write Scratchpad 
ds.write(0xBE); // Read Scratchpad 
ds.write(0x48); // Copy Scratchpad
ds.write(0xB8); // Recall EEprom 
ds.write(0x44); // Convert Sensor 
ds.write(0x45); // Read Sensor 
ds.write(0x01); // Reset Counter 
ds.write(0x02); // Read Counter 
ds.write(0x03); // Read IO-identification
ds.write(0xF3); // Setup PortA 
ds.write(0xF4); // Setup PortB 
ds.write(0xF5); // Read PortA 
ds.write(0xF6); // Read PortB 
ds.write(0xF7); // Write PortA 
ds.write(0xF8); // Write PortB 

 

Romosyto
Offline
Зарегистрирован: 15.01.2014

Спасибо за наводку))) А Вы это все из даташита вычитали? Я просто видимо не нашел или не понял как именно эти коды выделить из тех таблиц. Буду пробовать

n1ki7a
Offline
Зарегистрирован: 17.02.2014

Romosyto, у вас получилось разобраться как работать с ds2406?

Romosyto
Offline
Зарегистрирован: 15.01.2014

Да, получилось) Код дома на компе. Вечером отпишусь...

n1ki7a
Offline
Зарегистрирован: 17.02.2014

Ок. Жду. Спасибо.

Romosyto
Offline
Зарегистрирован: 15.01.2014

После безуспешных поисков на форумах и в инете, вот что удалось набыдлокодить)) :

#include <OneWire.h>

OneWire ds(9); //У меня шина на входе 9
uint8_t address[8] = {0x12, 0x2E, 0xED, 0x3D, 0, 0, 0, 0xC7}; //Адрес устройства (заменить на ваш)
uint8_t CHANNEL_ACCESS = 0xF5; //1 byte
uint8_t CHANNEL_CONTROL_BYTE = 0x44; //ALR=0;IM=1;TOG=0;IC=0;CHS1=0;CHS0=1;CRC1=0;CRC0=0 (NO CRC)
uint8_t data;
int alarm = 0;

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

void loop(void)
{
ds.reset();
ds.select(address);
ds.write(CHANNEL_ACCESS);
ds.write(CHANNEL_CONTROL_BYTE);
ds.write(0xFF);
data = ds.read();
ds.reset();
Serial.print("DATA BIN = ");
Serial.println(data, BIN);
Serial.print("STATUS = ");
  if (byte bitRead(data,2) == 1 && alarm < 5) 
  {
    alarm +=1;
    Serial.println("WARNING!!!");
  }
  else if (byte bitRead(data,2) == 1 && alarm >= 5)
  {
    alarm = 5;
    Serial.println("ALARM");
  }
  else 
  {
    Serial.println("OK");
  }  
  if (byte bitRead(data,2) == 0 && alarm > 0) 
  {
    alarm = 0;
  }
Serial.println("------------------------");
delay(3000);
}

Пояснения к коду:

У меня микросхема в двухканальном исполнении и мне нужно получить состояние входа PIO A.

Для того чтобы получить состояние портов необходимо обратиться либо к памяти устройства (до этого у меня мозгов не хватило) либо послать устройству сигнал CHANNEL ACCESS 0xF5 а затем так называемый CHANNEL CONTROL BYTE, в котором в каждом бите зашифровано, что Вы хотите получить от устройства.

У меня это значение 0x44;

А это расщифровка каждого байта по даташиту

ALR=0;IM=1;TOG=0;IC=0;CHS1=0;CHS0=1;CRC1=0;CRC0=0 (NO CRC)

CHS1=0 и CHS0=1 формируют запрос к PIO A;

IC=0 устанавливает асинхронный режим передачи. Так как у меня одноканальное чтение, то ставим 0

IM=1 и TOG=0 устанавливают режим чтения из выбранного порта

CRC1=0 и CRC0=0 отключают режим формирования CRC (Опытным путем выяснил, что при простом чтении состояния, CRC не формируется, поэтому установил нули)

ALR=0 - какая-то хрень с защелкой. Толком не удалось разобраться (вроде вычитал, что надо поставить ноль)

После отправки CHANNEL CONTROL BYTE к устройству, оно передает вам в ответ CHANNEL INFO BYTE, в каждом бите которого зашифровано состояние устройства. По даташиту меня интересовал байт 2, который передает состояние PIO A (для PIO B это байт 3).

Далее чтобы искючить ложные срабатывания (а такое опытным путем установлено, что бывает), я подряд 5 раз читаю состояние PIO A и если они подряд идут сработавшими - то вывожу "АВАРИЯ".

Код может и не изящен, но чем богаты так сказать)) Получится разобраться с CRC и памятью - поделитесь опытом)

n1ki7a
Offline
Зарегистрирован: 17.02.2014

Большое спасибо. Попробую. Если что-то додумаю обязательно поделюсь.

n1ki7a
Offline
Зарегистрирован: 17.02.2014
#include <OneWire.h>

OneWire ds(13);
 
uint8_t ds1[8] = {0x12, 0xF3, 0xF7, 0xA0, 0, 0, 0, 0xF4};

#define CHANNEL_ACCESS 0xF5;
#define CHANNEL_CONTROL_BYTE 0x45;
 
void setup() 
{
    Serial.begin(9600);
}
 
void loop() 
{
 
  uint8_t buf[7];

  ds.reset();
  ds.select(ds1);
    
  buf[0] = CHANNEL_ACCESS;
  buf[1] = CHANNEL_CONTROL_BYTE;
  buf[2] = 0xFF;

  ds.write_bytes(buf, 3);
  ds.read_bytes(buf+3, 4);     // 3 cmd bytes, 1 data byte, 1 0x00, 2 CRC16
  ds.reset();
  
  if (!OneWire::check_crc16(buf, 5, &buf[5])) {
     //если контрольная сумма не верна - возврат
     return;
  }
  
  Serial.print("  DS2406 data = ");
  //вывод CHANNEL INFO BYTE
  Serial.println(buf[3], BIN);
}

вот что у меня получилось.

Romosyto
Offline
Зарегистрирован: 15.01.2014

И как? работает?

Можно по подробнее про CRC?

Про вот эту строчку "// 3 cmd bytes, 1 data byte, 1 0x00, 2 CRC16" ?

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

Жаль что вопросы Romosyto за 8 лет так и не отвечены...

Приехала ко мне эта самая ds2406. После поиска и чтения даташита вижу что нужен пример работы с этой штукой.

Дело в том что  автор  библиотекой http://github.com/dustin/arduino-2406 явно не докурил все возможности чипа.

Мне пока интересна запись в устройство. Т.е. вывод сигнала на его порт

Код примера БлинкБезДелеяDS2406 на порту А

#include <OneWire.h>

#define ONE_WIRE_PIN   A4

OneWire myWire(ONE_WIRE_PIN);

uint8_t CHANNEL_ACCESS = 0xF5;


#define CHANNEL_CONTROL_BYTE_1_ALR  0x80 //ALR=0  not changed if reset
#define CHANNEL_CONTROL_BYTE_1_IM   0x40 //IM=1 - чтение, при чередовании чтение первое  
#define CHANNEL_CONTROL_BYTE_1_TOG  0x20 //TOG=1 - чередование чтения и записи TOG=0  Write all bits to the selected channel
#define CHANNEL_CONTROL_BYTE_1_IC   0x10 //IC=0  - asynchronous mode
#define CHANNEL_CONTROL_BYTE_1_CHS1 0x08 //CHS1=1 CHS0=0  channel B only  
#define CHANNEL_CONTROL_BYTE_1_CHS0 0x04 //CHS1=0 CHS0=1  channel A only
#define CHANNEL_CONTROL_BYTE_1_CRC1 0x02 // CRC1=0 CRC0=0 no CRC, 01 -CRC after every byte
#define CHANNEL_CONTROL_BYTE_1_CRC0 0x01 //   10 - CRC after 8 bytes 11-CRC after 32 bytes


uint8_t CHANNEL_CONTROL_BYTE = CHANNEL_CONTROL_BYTE_1_CHS0; //канал А на вывод данных без CRC

uint8_t cib;

void setup() {
  // put your setup code here, to run once:
 myWire.reset();
// myWire.select(addrArray);
 myWire.skip();
 myWire.write(CHANNEL_ACCESS,1);
 myWire.write(CHANNEL_CONTROL_BYTE,1);
 myWire.write(0xFF,1);
 cib=myWire.read();
}


void loop() 
{
  // put your main code here, to run repeatedly:
uint8_t t;
static uint8_t t0;
static uint8_t b;

  t=millis();
  if((uint8_t)(t-t0)>=200)
  {
   t0=t;
   myWire.write_bit(b);
   b^=1;
  }
}

Самое интересное - стр.47

Быстрый вывод одного бита прямо в пор. Как видим его можно повторять до сконания века или ресета шины. Очевидно вывод защищен от помех только везением, зато очень быстрый и простой. Если вместо одного бита выводить сразу байт, то будет воспринято как последовательные 8 бит. Можно задействовать оба порт, тогда передаваемые биты поочередно будут выводится то в один, то в другой. Можно даже синхронизировать процесс.

Ввод данных аналогичным путем так же возможен.

Похоже такой скоростной вывод позволит делать занятные вещи на 1Wire. Например поцепить серву. Или эмулировать I2C и поцепить что то типа 1604.

В 2413 похоже такого нет. 

Битовые операции OneWire не во всех описаниях есть, похоже в старых версиях их воще не было.