Протокол 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 Нуб

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

    longpastgone Нуб

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