Протокол OneWire: ведущий и ведомый

Тема в разделе "Глядите, что я сделал", создана пользователем CryNET, 29 янв 2016.

  1. CryNET

    CryNET Гик

    Всем привет!

    Хочу поделиться наработками с данным протоколом, а конкретно симуляция контроллера в качестве ведомого устройства.
    Изначально планировал сделать симуляцию таблетки iButton, но об этом позже.

    Протокол элементарный и этим он хорош. Подробнее о его принципах работы можно почитать тут.
    Для симуляции ведомого устройства я использовал готовую либу с робокрафта OneWireSlave.

    Пример работы.
    Ведомое устройство получает данные и отвечает "наоборот".

    Код (C++):
    #include <OneWireSlave.h>
    #define pin 13

    OneWireSlave ds(pin);
    unsigned char rom[8] = {0x01, 0xAD, 0xDA, 0xCE, 0x0F, 0x00, 0x00, 0xFF}; //адрес устройства, 8 байт по протоколу
    //Последний байт (CRC8 сумма) считать самому не обязательно, метод setRom() автоматически рассчитает его.
    char buf[5]; //Буфер для приема 5 байт данных (опционально)

    void setup() {
      Serial.begin(9600);
      ds.setRom(rom); //Сам рассчитывает CRC8 сумму адреса и устанавливает его. setRomnc() - не рассчитывает CRC8, оставляя массив адреса неизменным.
    }

    void loop() {
      ds.waitForRequest(false); //Ждем обращения
      ds.recvData(buf, sizeof(buf)); //Принимаем данные
      for(int i=sizeof(buf)-1; i>=0; i--){
        ds.send(buf[i]); //Отвечаем наоборот
      }
    }
    Данный код работает (проверялся) на ATtiny45, ATtiny84, ATMega328P (Скорее всего и на других работает, это все те, которые у меня имеются для опытов :) )

    Код ведущего устройства:
    Код (C++):
    #include <OneWire.h>
    #define pin 13

    OneWire ds(pin);
    unsigned char addr[8];
    byte mesg[5] = {'H', 'E', 'L', 'L', 'O'};

    void setup() {
      Serial.begin(9600);
      //delay(1000);
    }
    void loop() {
      if ( !ds.search(addr)) {
        ds.reset_search();
        return;
      }
      Serial.print("ROM =");
      for(int i = 0; i < 8; i++) {
        Serial.write(' ');
        Serial.print(addr[i], HEX);
      }
      Serial.println();
      if (OneWire::crc8(addr, 7) != addr[7]) {
          Serial.println("CRC is not valid!");
          return;
      }
      for(int i=0; i<sizeof(mesg); i++){
        ds.write(mesg[i]); //Отправляем 5 байт сообщения HELLO
      }
      for(int i=0; i<sizeof(mesg); i++){
        Serial.print((char)ds.read()); //Получаем 5 байт OLLEH (устройство отвечает наоборот)
      }
    }
    Собственно с iButton.
    Код таблетки:
    Код (C++):
    #include "OneWireSlave.h"

    char rom[8] = {0x01, 0xAD, 0xDA, 0xCE, 0x0F, 0x00, 0x00, 0x00}; //Адрес таблетки (ключ)
    OneWireSlave ds(8);

    void setup() {
        ds.setRom(rom);
    }

    void loop() {
        ds.waitForRequest(false);
    }
    Прошивал этим скетчем любой микроконтроллер. Arduino UNO, в роли ведущего(домофон) с помощью библиотеки OneWire видит как оригинальный ключ-таблетку, так и симулирующего таблетку микроконтроллер. И то и то видит.
    Все просто и теоретически должно работать.
    Но, к сожалению, домофоны (разных фирм и моделей) не видят симулятора.

    Конечно странно, что ардуино видит и того и того, а домофон нет.
    Я полагаю, что алгоритм у OneWire библиотеки для Arduino более лоялен к тайм-слотам протокола, нежели у домофонов. Скорее всего у домофонов более короче тайм-слоты или необходимо более длительное удержание "1" или "0".
    К сожалению я не могу это проверить, т.к. у меня нету необходимого оборудования чтобы посмотреть что происходит и где не успевает.

    Но, как протокол для обмена данными между устройствами он достаточно хорош, т.к. для обмена необходимо всего 2 провода: GND(минус) и DATA(питание и данные).

    P.S. Буду рад, если у кого-то будет желание довести дело до конца или знает в чем тут загвоздка :)
     
    Alex19, avegad, vvr и 3 другим нравится это.
  2. avegad

    avegad Нуб

    Привет CryNet.

    А схемой подключения двух ардуин(одна мастер, другая slave) по 1-wire не поделитесь? Насколько я понимаю если просто соединить у ардуин GND и DATA - работать не будет, нужно ещё что то, да гугль говорит что не так всё просто.
     
  3. CryNET

    CryNET Гик

    Да тут всё как у всех:
    [​IMG]
    В данном случае ведущая-arduino - Digital PIN использует, а ведомая-arduino - это IC 1 или IC 2
    Главное GND не забудьте общим сделать с устройствами и блоком питания (если отдельный)
     
  4. prgserg

    prgserg Нуб

    Добрый день. Организовываю связь по 1-wire между двумя arduino uno. Использовал ваши скетчи (одна ведущая, другая ведомая). Ведущая видит адрес ведомой, но при передаче данных происходит какой то затык. А именно, ведомая ардуино не принимает ничего. Код копировал полностью. Как вы думаете, в чем может быть причина. Повторю еще раз... адрес ведомой ардуино ведущая считывает и выводит, т.е. с подключением все ок...
     
  5. CryNET

    CryNET Гик

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

    + есть 2 версии библиотек, на сколько я помню. Я, вроде, вторую версию использовал.
     
  6. Я тоже попробовал и не получалось пока не изменил немного код
    Ведущий

    #include <OneWire.h>
    #define pin 13

    OneWire ds(pin);
    unsigned char addr[8];
    byte mesg[5] = {'H', 'E', 'L', 'L', 'O'};

    void setup() {
    Serial.begin(9600);
    //delay(1000);
    Serial.print("OK");
    }
    void loop() {
    if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
    }
    Serial.print("ROM =");
    for(int i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr, HEX);
    }
    Serial.println();
    if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
    }
    ds.reset();
    ds.select(addr);
    for(int i=0; i<sizeof(mesg); i++){
    ds.write(mesg); //Отправляем 5 байт сообщения HELLO
    }
    for(int i=0; i<sizeof(mesg); i++){
    Serial.print(char(ds.read())); //Получаем 5 байт OLLEH (устройство отвечает наоборот)
    }
    }
    И у ведомого нечего не менял
     
  7. _Стас_

    _Стас_ Нуб

    Добрый день.
    Совсем недавно начал осваивать платформу Ардуино. Этап "мигания диода" и "поворот шагового двигателя" успешно прошел. Есть реальная задача. Необходимо на основе ардуино, желательно Nano (исходя из размеров) сделать нечто в виде усилителя сигнала по шине 1-Wire, "что пришло, то и ушло". Есть мнение, что дальше 25 метров сигнал сильно затухает. Мне подойдет первый скетч в этом форуме или все таки второй? Ну за исключением того, что отправлять надо в прямом порядке, а не в обратном. Спасибо.
     
  8. РоманVar

    РоманVar Нуб

    Здравствуйте!
    Создал тему, возможно вам это будет интересно. Пожалуйста, свяжитесь со мной!