Перейти к содержанию

Работа с двумя датчиками DS18B20. Проблема фиксации адреса


gorlanovmax

Рекомендуемые сообщения

Доброго времени суток, уважаемые форумчане.

Реализую проект.

В устройстве имеется внутренний датчик температуры и как опция внешний.

Измерение двух температур реализуется без проблем.

Сейчас работает вот в таком виде

#include <ds18b20.h>                      //        //библиотека для работы с датчиком ds18b20
#include <1wire.h>                                 //1-wire библиотека
unsigned char rom_codes[2][9];                     //массив для датчиков в оперативке
#define MAX_DS18B20 2                             //максимально 2 датчика
unsigned char devices;                            //переменная для кол-ва датчиков
float temper;                                     // переменная в которой количество 
int temp_0,temper_fl,minus=0;                       // обьявляем перменные


void read_temp(unsigned char temp_num)
{
    #asm("wdr")
    temper=ds18b20_temperature(&rom_codes[temp_num][0]);
    temp_0=temper;                                // отбор целой части от температуры 
    if(temper<0)                                  // при отрицательной температуре  
        {
        temper_fl=(temper-temp_0-0.0625)*10;      // дробная часть 
         temp_0=-((temp_0*10)+temper_fl);         // температура*10 
         minus=1;                                   // минус
        }else                                     // при положительной 
            {
             minus=0;                               // плюс 
             temper_fl=(temper-temp_0)*10;        // дробная часть 
             temp_0=(temp_0*10)+temper_fl;        // температура*10 
            }    
        if ((temp_0 < 1300) & (temp_0 > 0))       // установим порог 
        temp_0= temp_0;
        else
        {
        temp_0 =0;                 
         } 
}
  
void lcd_temp(unsigned char temp_num)    //вывод температуры на экран
{
    int i,poz;
    #asm("wdr")
    for(i=0; i<8; i++)
    {
        poz=i*12;
        char_12_16(10,poz,6);              //затираем нижнюю строку 
    }    
    decbin_ds(temp_0);
    char_12_16(13,6,6);   //14 выводим градусник
    if (temp_num==0) 
    {

        if (minus>0) {char_12_16(17,20,6);}     // выводим "IN -"
        else {char_12_16(14,20,6);}             // выводим "IN +"
    }    
    else 
    {
        if (minus>0) {char_12_16(19,20,6);}     // выводим "OUT -"
        else {char_12_16(16,20,6);}             // выводим "OUT +"
    }    
    gotoxy(56,7);print_char(44);    // запятая
    char_12_16(c2,32,6);              //выводим цифру 1
    char_12_16(c1,44,6);              //выводим цифру 2
    char_12_16(c0,61,6);              //выводим десятую часть 
    char_12_16(25,78,6);              //выводим значок градуса
}
  
  
void main(void)
{
int i, time_sec2=0;
  
//работа с температурой
devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_codes);  //определим сколько устройств   подключено к шине 1-Wire 
ds18b20_init(0,-35,50,DS18B20_12BIT_RES);        // переключения термометра в 12 битный режим 
w1_init();                                  // Wire Bus initialization
  
#asm("sei")


    while (1)
    {           
        #asm("wdr")       
        if (time_sec>=1)            // таймер 1 сек
        {
            #asm("wdr")
            TIMER0_STOP;            // стоп таймер 0
            char_24_32(11,8,1);             //выводим колонку
            real_fuel=read_adc(2);  // чтение датчика топлива
            time_sec=0;             // сбрасываем счетчик секунд
            time_sec2=time_sec2+1;
            if (time_sec2<3) {lcd_volt();}   //вывод напряжения + значок         
            if ((time_sec2>=3) & (time_sec2<5)) {read_temp(0); lcd_temp(0);}// вывод температуры, внутр.датчик                   
            if ((time_sec2>=5) & (time_sec2<7)) {read_temp(1); lcd_temp(1);}// вывод температуры, наруж.датчик          
            if (time_sec2>=7) {time_sec2=0;}      //сброс таймера вывода нижней строки
            lcd_fuel();
            TIMER0_START;           // старт таймер 0
        };
    }      
}  
  

 

Все отлично показывает, но нет привязки к конкретным датчикам.

А схема необходима следующая:

При первом включении к прибору подключен только один внутренний датчик температуры (он заяпаян на плате).

При этом он должен прописаться в память и показываться как внутренний.

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

При последующих включениях поиск будет уже не нужен.

 

Пытаюсь сделать следующее:

Добавляю массив, аналогичный rom_codes только пихаю его в eeprom.

После инициализации проверяю массив в eeprom на заполненность, если пустой, заполняю сначала первый датчик потом второй.

Далее пробовал два варианта:

1. указать массив eeprom в функции ds18b20_temperature - не работает. дает ошибку несовместимости типов, хотя массивы идентичные.

2. вновь записанный массив eeprom выгружаю обратно в rom_codes - работает, но на выходе температуру не выдает.

Привожу код по второму варианту

#include <ds18b20.h>                      //        //библиотека для работы с датчиком ds18b20
#include <1wire.h>                                 //1-wire библиотека
unsigned char rom_codes[2][9];  //массив для датчиков в оперативке
eeprom unsigned char e_rom_codes[2][9]={{0},{0}};   //массив в памяти для датчиков
#define MAX_DS18B20 2
unsigned char devices;
float temper;                                     // переменная в которой количество 
int temp_0,temper_fl,minus=0;                       // обьявляем перменные

void read_temp(unsigned char temp_num)  //замер температуры, указываем номер датчика 0 или 1
{
    #asm("wdr")
    temper=ds18b20_temperature(&rom_codes[temp_num][0]);
    temp_0=temper;                                // отбор целой части от температуры 
    if(temper<0)                                  // при отрицательной температуре  
        {
        temper_fl=(temper-temp_0-0.0625)*10;      // дробная часть 
         temp_0=-((temp_0*10)+temper_fl);         // температура*10 
         minus=1;                                   // минус
        }else                                     // при положительной 
            {
             minus=0;                               // плюс 
             temper_fl=(temper-temp_0)*10;        // дробная часть 
             temp_0=(temp_0*10)+temper_fl;        // температура*10 
            }    
        if ((temp_0 < 1300) & (temp_0 > 0))       // установим порог 
        temp_0= temp_0;
        else
        {
        temp_0 =0;                 
         } 
}

void lcd_temp(unsigned char temp_num)   //вывод температуры на экран (указываем номер датчика 0 или 1)
{
    int i,poz;
    #asm("wdr")
    for(i=0; i<8; i++)
    {
        poz=i*12;
        char_12_16(10,poz,6);              //затираем нижнюю строку 
    }    
    decbin_ds(temp_0);
    char_12_16(13,6,6);   //14 выводим градусник
    if (temp_num==0) 
    {

        if (minus>0) {char_12_16(17,20,6);}     //26 выводим "IN -"
        else {char_12_16(14,20,6);}             // выводим "IN +"
    }    
    else 
    {
        if (minus>0) {char_12_16(19,20,6);}     //26 выводим "OUT -"
        else {char_12_16(16,20,6);}             // выводим "OUT +"
    }    
    gotoxy(56,7);print_char(44);    // запятая
    char_12_16(c2,32,6);              //выводим цифру 1
    char_12_16(c1,44,6);              //выводим цифру 2
    char_12_16(c0,61,6);              //выводим десятую часть 
    char_12_16(25,78,6);              //выводим значок градуса
}

void main(void)
{
int i, time_sec2=0;

devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_codes);  //определим сколько устройств   подключено к шине 1-Wire 
if (e_rom_codes[0][0]==0)                      //если в eeprom пусто, записываем данные первого датчика
{
    for (i=0;i<9;i++)
    {e_rom_codes[0][i]=rom_codes[0][i];}
}
if (e_rom_codes[1][0]==0)                    //проверяем запись второго датчика 
{
    if (e_rom_codes[0][0]==rom_codes[0][0]) //если первый датчик уже записан в первую ячейку 
    {
        for (i=0;i<9;i++)
        {e_rom_codes[1][i]=rom_codes[1][i];}
    }
    else                                    //если первый датчик при подключении сразу двух стал вторым, то записываем второй датчик из первой ячейки во вторую
    {
        for (i=0;i<9;i++)
        {e_rom_codes[1][i]=rom_codes[0][i];}
    }
}
ds18b20_init(0,-35,50,DS18B20_12BIT_RES);        // переключения термометра в 12 битный режим 
w1_init();                                  // Wire Bus initialization
for (i=0;i<9;i++) {rom_codes[0][i]=e_rom_codes[0][i];}
for (i=0;i<9;i++) {rom_codes[1][i]=e_rom_codes[1][i];}

    while (1)
    {           
        #asm("wdr")       
        if (time_sec>=1)            // таймер 1 сек
        {
            #asm("wdr")
            GABARIT;                // проверка включения габаритов
            TIMER0_STOP;            // стоп таймер 0
            char_24_32(11,8,1);             //выводим колонку
            real_fuel=read_adc(2);  // чтение датчика топлива
            if (inertnost>1)       // если инертность не равна 0
            {
                works_inertnost();  // обработка инертности                  
            }
            time_sec=0;             // сбрасываем счетчик секунд
            time_sec2=time_sec2+1;
            if (time_sec2<3) {lcd_volt();}   //вывод напряжения + значок         
            if ((time_sec2>=3) & (time_sec2<5)) {read_temp(0); lcd_temp(0);}// вывод температуры, внутр.датчик                   
            if ((time_sec2>=5) & (time_sec2<7)) {read_temp(1); lcd_temp(1);}// вывод температуры, наруж.датчик          
            if (time_sec2>=7) {time_sec2=0;}      //сброс таймера вывода нижней строки
            lcd_fuel();
            TIMER0_START;           // старт таймер 0
        };
    }      
}  

 

Не могу сообразить почему не работает. И как проще реализовать память и обращение к конкретному датчику

Изменено пользователем gorlanovmax
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

14 часа назад, gorlanovmax сказал:

указать массив eeprom в функции ds18b20_temperature - не работает. дает ошибку несовместимости типов, хотя массивы идентичные

Потому, что функция принимает на входе указатель на область RAM, а вы ей суёте со спецификатором eeprom.
Копируйте из EEPROM в область ОЗУ и потом уже подкидывайте в функцию указатель.
 

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

1 час назад, Alex сказал:

Копируйте из EEPROM в область ОЗУ и потом уже подкидывайте в функцию указатель.
 

так я же написал, что копирую. Все равно не работает.

Код приведен именно  с копированием

devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_codes);  //определим сколько устройств   подключено к шине 1-Wire 
if (e_rom_codes[0][0]==0)                      //если в eeprom пусто, записываем данные первого датчика
{
    for (i=0;i<9;i++)
    {e_rom_codes[0][i]=rom_codes[0][i];}
}
if (e_rom_codes[1][0]==0)                    //проверяем запись второго датчика 
{
    if (e_rom_codes[0][0]==rom_codes[0][0]) //если первый датчик уже записан в первую ячейку 
    {
        for (i=0;i<9;i++)
        {e_rom_codes[1][i]=rom_codes[1][i];}
    }
    else                                    //если первый датчик при подключении сразу двух стал вторым, то записываем второй датчик из первой ячейки во вторую
    {
        for (i=0;i<9;i++)
        {e_rom_codes[1][i]=rom_codes[0][i];}
    }
}
ds18b20_init(0,-35,50,DS18B20_12BIT_RES);        // переключения термометра в 12 битный режим 
w1_init();                                  // Wire Bus initialization
for (i=0;i<9;i++) {rom_codes[0][i]=e_rom_codes[0][i];}
for (i=0;i<9;i++) {rom_codes[1][i]=e_rom_codes[1][i];}

 

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Компилятор CodeVisionAVR

А как может по другому производиться чтение?

Все остальные переменные из памяти читаются именно так

Изменено пользователем gorlanovmax
Ссылка на комментарий
Поделиться на другие сайты

Добрый день,

 

Вопрос решен.

Решился корректировкой массивов

для корректной работы необходим массив следующей размерности:

массив [кол-во датчиков][9]

 

У меня так и было поставлено, но при записи в eeprom я делал цикл на 8 знаков, а в массиве 9.

Отсюда и ошибка

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, gorlanovmax сказал:

для корректной работы необходим массив следующей размерности:

массив [кол-во датчиков][9]

У меня так и было поставлено, но при записи в eeprom я делал цикл на 8 знаков, а в массиве 9.

Очередное доказательство вреда магических чисел. Ваш код просто пропитан ими, наверняка проблема не последняя...

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Только что, gorlanovmax сказал:

Буду благодарен за совет, как улучшить код.

Избавьтесь от магических чисел, для чего используйте инструмент описания макросов-констант. Сравните со своим кодом:

#define ROM_SIZE	9

unsigned char rom_codes[MAX_DS18B20][ROM_SIZE];  //массив для датчиков в оперативке
eeprom unsigned char e_rom_codes[MAX_DS18B20][ROM_SIZE]={{0},{0}};   //массив в памяти для датчиков

// копирование адресов из EEPROM в ОЗУ
for(d=0; d<MAX_DS18B20; d++)
	for (i=0;i<ROM_SIZE;i++) rom_codes[d][i]=e_rom_codes[d][i];

Одна константа ROM_SIZE на 100% гарантирует, что нигде и никогда вы не ошибетесь в количестве элементов массива (если, конечно, будете использовать эту константу, а не магическое число)! И когда вам приспичит изменить количество датчиков, это придется сделать только в одном месте - при описании константы MAX_DS18B20, которая у вас уже есть, но почему-то не применяется.

Я привел только кусочек кода, магические числа у вас насквозь пропитали ваш код - если вы просто замените эту магию, и, где надо, воспользуетесь этим для оптимизации (как в моем примере - цикл по количеству датчиков, а не копипастинг строчек) - вы увидите заметное улучшение качества кода.

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...