Прикрутить onewire интерфейс к аналоговму пину

Тема в разделе "Arduino & Shields", создана пользователем Nekto_nikto, 10 сен 2020.

  1. Nekto_nikto

    Nekto_nikto Гик

    Нет дело не в разъемах, в этом я уверен.
    Плата обычная MKS base v1.4
    распиновку платы прикрепляю, там кстати тоже указано, что пины эти цифровые, но что то пошло не так...

    В самой библиотеке oneWire кстати подсмотрел как она по этому интерфейсу с устройствами общается, через in/out, может от этого все зло?
     

    Вложения:

  2. akl

    akl Гуру

    а RX0 где находится и как к нему датчик подключался? кстати что за датчик? ds18b20?
    хотя это не объясняет поведение светодиодов.
     
  3. Nekto_nikto

    Nekto_nikto Гик

    RX0 это PE0, он же 2 пин меги
    с датчиком угадали, а что с ним не так?

    Попробывал на всякий случай еще ADC отключить через

    Код (C++):
    ADCSRA&=(0 << ADEN);       // Отключаем ADC
    ADCSRA&=(0 << ADIE);       // Отключаем прерывание ADC
    никаких изменений.
     
    Последнее редактирование: 11 сен 2020
  4. akl

    akl Гуру

    PE0 это 2 нога микросхемы, а на плате "ардуино мега" это digital pin 0, и чет я не вижу где он на этом рисунке MKS Base

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

    Nekto_nikto Гик

    На этой плате стоит ATMega 2560 16AU, там много каких пинов не увидите, часть используется для общения с LCD экраном, часть для управления драйверами шаговиков, но т.к. там уже стоят разведенные и распаяные полевики на определенных пинах, я считаю для себя этот вариант очень не плохим, т.к. не нужно париться по этому поводу, да и дешевле думаю будет чем самому что то подобное делать.
    Со вторым датчиком, который не рабочий выписывал и переходник с подтягивающим резистором и еще каким то smd элементов, при его использовании разницы не заметил, хотя конечно если датчик паленый прислали, могли и переходник такой же - гулять так гулять.
    Но опять же рабочий датчик показывает вменяемые значения температур порядка 20C, и поэтому я склонен думать, что датчик рабочий. Правда с термопарой и мультиметром точность показаний пока не проверял.
     
  6. akl

    akl Гуру

    это не отменяет того, что D2 это не PE0, а PE4. впрочем от этого становится еще непонятнее почему на PE4 датчик работает, а на PE5 нет
     
  7. b707

    b707 Гуру

    ну если ТС уже давно так экспериментирует - может на плате половина портов уже "того"...
    У него вон и датчик Ds один уже сдох. и переходники из китая "глючные"... складывается впечатление что у ТС рука тяжелая...или просто день был неудачным
     
  8. Nekto_nikto

    Nekto_nikto Гик

    Ну так я то в управляющей программе свои пины прописываю просто цифрами, так что у меня 2 и 3 это PE0 и PE1.
     
  9. Nekto_nikto

    Nekto_nikto Гик

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

    akl Гуру

    если программа написана в ардуино-иде, то digitalWrite(2, HIGH); включит PE4
     
  11. Nekto_nikto

    Nekto_nikto Гик

    И все эти нерабочие и один рабочий пины могут быть связаны/не связаны с внешними прерываниями..., но опять же я эти прерывания не прописывал, равно как и не программировал еще чипы 2560, может быть сама среда что то на них вешает, хотя это похоже на бред.
     
  12. akl

    akl Гуру

    можно взять мультиметр и померить что там происходит с напряжением на всех контактах этих разъемов когда там светодиод пытается моргать.
     
  13. Nekto_nikto

    Nekto_nikto Гик

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

    к тому же как я понял не я первый с таким вопросом
    https://forum.arduino.cc/index.php?topic=623304.0
     
  14. akl

    akl Гуру

    то есть светодиоды уже заработали? и в чем там была проблема?
     
  15. akl

    akl Гуру

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

    Код (C++):
    //DS18B20
    #define DS_DDR DDRB
    #define DS_PORT PORTB
    #define DS_PIN PINB
    #define DS_P 5
    unsigned char Temp_H, Temp_L, OK_Flag, temp_flag;
    // Инициализация DS18B20
    unsigned char DS18B20_init(void)
    {
        DS_DDR |= (1 << DS_P); //  - выход
        DS_PORT &= ~(1 << DS_P); // Устанавливаем низкий уровень
        _delay_us(490);
        DS_DDR &= ~(1 << DS_P); //  - вход
        _delay_us(68);
        OK_Flag = (DS_PIN & (1 << DS_P)); // Ловим импульс присутствия датчика
        // если OK_Flag = 0 датчик подключен, OK_Flag = 1 датчик не подключен
        _delay_us(422);
        return OK_Flag;
    }
    // Функция чтения байта из DS18B20
    unsigned char read_18b20(void)
    {
        unsigned char i, data = 0;
        for(i = 0; i < 8; i++)
        {
            DS_DDR |= (1 << DS_P); //  - выход
            _delay_us(2);
            DS_DDR &= ~(1 << DS_P); //  - вход
            _delay_us(4);
            data = data >> 1; // Следующий бит
            if(DS_PIN & (1 << DS_P)) data |= 0x80;
            _delay_us(62);
        }
        return data;
    }
    // Функция записи байта в DS18B20
    void write_18b20(unsigned char data)
    {
        unsigned char i;
        for(i = 0; i < 8; i++)
        {
            DS_DDR |= (1 << DS_P); //  - выход
            _delay_us(2);
            if(data & 0x01) DS_DDR &= ~(1 << DS_P);
            else DS_DDR |= (1 << DS_P);
            data = data >> 1; // Следующий бит
            _delay_us(62);
            DS_DDR &= ~(1 << DS_P); //  - вход
            _delay_us(2);
        }
    }


    int ds18gettemp(){
        unsigned int buffer;
        //unsigned int temp_point;
        int tem;
        DS18B20_init();        // Инициализация DS18B20
        write_18b20(0xCC);     // Проверка кода датчика
        write_18b20(0x44);     // Запуск температурного преобразования
        //_delay_ms(100);       // Задержка на опрос датчика
        DS18B20_init();        // Инициализация DS18B20
        write_18b20(0xCC);     // Проверка кода датчика
        write_18b20(0xBE);     // Считываем содержимое ОЗУ
        Temp_L = read_18b20(); // Читаем первые 2 байта блокнота
        Temp_H = read_18b20();
        //_delay_ms(100);
        temp_flag = 1;         // Флаг знака температуры равен 1(плюс)
        // Вычисляем отрицательную температуру
        if(Temp_H &(1 << 3))   // Проверяем бит знака температуры на равенство единице
        {
            signed int temp;
            temp_flag = 0;      // Флаг знака равен 0(минус)
            temp = (Temp_H << 8)|Temp_L;
            temp = -temp; // Переводим дополнительный код в прямой
            Temp_L = temp;
            Temp_H = temp >> 8;
        }
        // Вычисляем целое значение температуры
        buffer = ((Temp_H << 4) & 0x70)|(Temp_L >> 4);
        tem=buffer;
        /*// Вычисляем дробное значение температуры
        if(temp_flag == 0) buffer = (Temp_L & 0x0F) + 1; // Корректировка
        else buffer = (Temp_L & 0x0F);
        temp_point = buffer * 625 / 1000; // Точность темпер.преобразования(0.0625)
        */

        return tem;
    }
     
    по идее это легко перезатачивается под любую другую атмегу на любую ее ногу
     
  16. Nekto_nikto

    Nekto_nikto Гик

    Так я ж писал что светодиод, которым я просто номер ноги искал засветил на такой ноге как 3 только после того как прописал analogWrite(3,255); а дальше я им мигал через digitalWrite();, не работает корректно как я понял именно библиотека OneWire, т.к. по ссылке выше у ТС такая же проблема, которую так и не решили, только у него плата ArduinoNANO была и он сначала вешал на аналоговый пин такой же как и у меня датчик температуры, который не работал, после чего он его прицепил на как он пишет цифровой пин и все пошло, и его вполне устроило. Было это аж в июне 2019, потом на этот же форум писали люди с аналогичной проблемой, но никто так и не решил, был там человек, который писал что onewire v2.3.5 решает проблему, только ничего она не решает, т.к. у меня именно эта версия и установлена.

    За код отдельное спасибо, завтра буду искать еще в нете, если ничего не найду, буду переписывать.
    А вот так у меня сделано, переписывал с примера из библиотеки вчера, так что не судите строго
    Код (C++):
    #include "pins.h"
    #include <OneWire.h>      // Требуется ручная установка из менеджера библиотек

    /*
    int pinSolderTCouple=A13;
    int solderTCouple;
    pinMode(pinSolderTCouple, INPUT);
    // Функция определения температуры термопары
    solderTCouple = map(analogRead(pinSolderTCouple), 0, 2000, 0, 140);*/


    String S="";              // Переменная передаваемая через COM порт
    byte data[2];             // Буфер, куда будут передаваться значения температур датчиков TANK_TEMP и ROOTS_TEMP
    byte TANK_addr[8];        // 2 буфера, куда записываются адреса устройств, с которых будем считывать данные
    byte ROOTS_addr[8];       // Вполне возможно можно указать массив 2 на 8, а в коде укзывать адреса первых элементов addr[2][8]->&addr[0][0];&addr[1][0]
    float TANK_TEMP_=0;       // Значение температуры TANK_TEMP
    float ROOTS_TEMP_=0;      // Значение температуры ROOTS_TEMP
    int16_t temp;             // Значение считанное с датчика
    int16_t *Pdata=(int16_t*)&data[0];     // Указатель на буфер

    long lastUpdateTime = 0;  // Переменная для хранения времени последнего считывания с датчика
    const int TEMP_UPDATE_TIME = 1000; // Определяем периодичность проверок

    OneWire ds1(TANK_TEMP);
    OneWire ds2(ROOTS_TEMP);

    void setup() {
      // put your setup code here, to run once:

    // Инициализируем пины
    pinMode(TANK_TEMP, INPUT_PULLUP);
    pinMode(ROOTS_TEMP, INPUT_PULLUP);
    //analogWrite(ROOTS_TEMP, 127);
    ADCSRA&=(0 << ADEN);       // Отключаем ADC
    ADCSRA&=(0 << ADIE);       // Отключаем прерывание ADC
    /*DDRA=DDRA&0b11110111;
    PORTA=PORTA|0b00001000;
    PINA=PINA&0b11110111;*/




    // Получаем адреса датчиков
    ds1.search(&TANK_addr[0]);
    ds1.search(&ROOTS_addr[0]);
    ds1.reset_search();
    ds2.reset_search();
    delay(250);   // Необходимая пауза

     
    Serial.begin(9600); // подключаем последовательный порт
    }



    void GetDS18B20_Temp()
    {
    ds1.reset();
    ds1.select(&TANK_addr[0]);
    ds1.write(0x44);            // Инициируем определение температуры датчиком
    ds2.reset();
    ds2.select(&ROOTS_addr[0]);
    ds2.write(0x44);            // Инициируем определение температуры датчиком
    delay(1000);

    ds1.reset();
    ds1.select(&TANK_addr[0]);
    ds1.write(0xBE);            // Читаем значение температуры датчика в баке
    data[0] = ds1.read();
    data[1] = ds1.read();
    temp=*Pdata;
    TANK_TEMP_=(float)temp/16;  // получили значение температуры для бака

    ds2.reset();
    ds2.select(&ROOTS_addr[0]);
    ds2.write(0xBE);            // Читаем значение температуры датчика в зоне корней
    data[0] = ds2.read();
    data[1] = ds2.read();
    temp=*Pdata;
    ROOTS_TEMP_=(float)temp/16;  // получили значение температуры для бака

    /*if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
      {
        lastUpdateTime = millis();
        ds1.reset();                   // Теперь готовимся получить значение измеренной температуры
        ds1.write(0xCC);
        ds1.write(0xBE);               // Просим передать нам значение регистров со значением температуры
        data[0] = ds1.read();          // Читаем младший байт значения температуры
        data[1] = ds1.read();          // А теперь старший
        TANK_TEMP_=*Pdata* 0.0625;     // получили значение температуры для бака

        lastUpdateTime = millis();
        ds2.reset();                   // Теперь готовимся получить значение измеренной температуры
        ds2.write(0xCC);
        ds2.write(0xBE);               // Просим передать нам значение регистров со значением температуры
        data[0] = ds2.read();          // Читаем младший байт значения температуры
        data[1] = ds2.read();          // А теперь старший
        ROOTS_TEMP_=*Pdata* 0.0625;    // получили значение температуры
      }*/

    }


    void loop() {
    // put your main code here, to run repeatedly:
    GetDS18B20_Temp(); // Получаем значения температуры в баке и в зоне корней
    //if(TANK_TEMP_!=0 || ROOTS_TEMP_!=0)   // Если значения получены, выводим
      //{
      S="TANK_TEMP="+(String)TANK_TEMP_;
      Serial.println(S);
      S="ROOTS_TEMP="+(String)ROOTS_TEMP_;
      Serial.println(S);
      //TANK_TEMP_=0;
      //ROOTS_TEMP_=0;
      //}

    }
     
  17. akl

    akl Гуру

    не могу вообразить механизм действия этого. как уже писал, analogWrite(3,255); это то же самое что pinMode(3, OUTPUT); digitalWrite(3,HIGH);

    и пин 3 не является аналоговым ни разу
     
  18. Nekto_nikto

    Nekto_nikto Гик

    Может быть еще не работает из-за отсутствия подтягивающего резистора на 4,7K, т.к. все туториалы, которые нашел в один голос твердят что без него работать не будет, т.к. он вроде как обеспечивает паразитное питание внутреннему EEPROM датчика, если китайцы в ту нерабочую приблуду, что прислали с нерабочим датчиком поставили нужный резистор, то завтра и этот вариант попробую.

    А светодиод у меня горел только так как я описал выше, при объявлении только pinMode и digitalWrite сразу гас.
     
  19. a1000

    a1000 Гуру

    Без этого резистора не заработает никогда. Он нужен не только для паразитного питания (вы к стати не написали как датчик у вас питается). Он нужен для самого протокола 1 wire. С помощью него формируются логические уровни на шине. Для общего понимания процесса можете посмотреть видео


    Ну очень доходчиво человек объясняет.
     
  20. parovoZZ

    parovoZZ Гуру

    Он нужен датчикам с шиной 1 wire. Мастеру он не нужен - мастер реализует как нижний драйвер, так и верхний. И не протоколу, а интерфейсу (шине). Протокол - это программная реализация общения.