Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » DS18B20 задержки


DS18B20 задержки

Сообщений 1 страница 17 из 17

1

Товарищи специалисты подскажите как избежать задержку при чтении/записи датчика температуры ds18b20. К атмеге 8 подключен цифровой светодиодный индикатор и датчик температуры. Отображение цифр осуществляется по таймеру. При опросе датчика цифры кратковременно гаснут, гдето на 70-100 милесекунд.
опрос датчика стандартный

Код:
.....
Config Timer0 = Timer , Prescale = 64 
On Timer0 Pulse :                   
..........
Do
1wreset
1wwrite &HCC                                                ' Выдаем команду чтения ПЗУ
1wwrite &H44                                                ' Запуск измерения

Waitms 900                                                  ' Ждем окончания преобразования

1wreset
1wwrite &HCC
1wwrite &HBE                                                ' Команда чтения ОЗУ датчика

Byte0 = 1wread()                                            ' Читаем нулевой байт
Byte1 = 1wread()                                            ' Читаем первый байт

T1 = Byte0 / 16                                             ' Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16                                             ' Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)
Temp = T1 + T2                                              ' Формирмируем результам

Waitms 1200

Loop
End

Pulse: 

.....
.....
программа вывода числа Temp на светодиодный цифровой индикатор
.....
.....
Return

0

2

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

0

3

Pasha
Привет. Подскажите а почему у Вас вот этот код

Код:
T1 = Byte0 / 16                                             ' Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16                                             ' Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)

Именно так а не иначе. Прочитал даташет , рекомендации, но так и не понял как и откуда берутся эти цифры. Почему Вы их сдвигаете?

0

4

Привет! Попробуй отображать цифры в момент ожидания преобразования.
В этом случае таймер можно вообще не использовать, а пользоваться задержками waitms.
У меня так все хорошо работает.

0

5

Dr.Michurin а можно поподробнее?

0

6

Помогите с кодом для 1820 нашёл программу на дисплеи показывает +3С температура комнатная

Код:
$regfile = "m32.dat" 
$crystal = 4000000
Config Lcd = 16 * 2 ‘ дисплей 2 строки по 16 символов
Config Lcdpin = Pin , Db4 = Portb.1 , Db5 = Portb.2 , Db6 = Portb.3 , Db7 = Portb.4 , E = Portb.5 , Rs = Portb.6 ‘ конфигурируем дисплей

Config 1wire = Portd.5 ‘ на эту ножку подключим DS18B20 и подтягивающий резистор на 4,7 ком к + питания


Dim Byte0 As Byte
Dim Byte1 As Byte
Dim Signtemperatura As String * 1
Dim T1 As Byte
Dim T2 As Byte
Dim I As Integer

Do
1wreset
1wwrite &HCC ‘ Выдаем команду чтения ПЗУ
1wwrite &H44 ‘ Запуск измерения

Waitms 750 ‘ Ждем окончания преобразования

1wreset
1wwrite &HCC
1wwrite &HBE ‘ Команда чтения ОЗУ датчика

Byte0 = 1wread() ‘ Читаем нулевой байт

Byte1 = 1wread() ‘ Читаем первый байт

If Byte1 >= 248 Then ‘ Проверяем на отрицательную температуру.248 в десятичном – 11111000 в двоичном. Если температура отрицательная – вычитаем из &HFF

Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Signtemperatura = "-"

Else
Signtemperatura = "+"
End If

T1 = Byte0 / 16 ‘ Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16 ‘ Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)

T1 = T1 + T2 ‘ Формирмируем результам и выдаем его на индикатор. Команда LCD сама преобразует его в десятичный вид

Cls
Lcd Signtemperatura ; T1 ; "C"
Wait 2
Loop
End

Отредактировано THX1138 (2010-12-21 00:04:59)

0

7

THX1138 написал(а):

Помогите с кодом для 1820

В коде ведь написано:

Config 1wire = Portd.5 ‘ на эту ножку подключим DS18B20 и подтягивающий резистор на 4,7 ком к + питания

0

8

Может ещё кому нужно. DS18B20с десятичной точкой, от минуса до плюса на весь предел измерения , работает как и по 2-х так и по 3-х проводной схеме включения, один датчик на шине. Контроль CRC с идикацией ошибок. Динамическая индикация без мерцания и задержек. кварц как внутренний так и внешний, задаётмя фьюзами. рабочая частота 8 Мгц. На дополнительном пине висит индикатор опроса датчика температуры для визуализции.

Код:
'Kuzmich Leonid 
'Ds18b20,CRC и динамическая индикация без задержки

$regfile = "attiny2313.dat"

$crystal = 8000000                                          'Рассчитано на кристалле 8 МГц

Ddrb = &B01111111                                           'Порт D 1-выход, 0-вход (сегменты)
Ddrd = &B01001111                                           'Порт B 1-выход, 0-вход (разряды)

Const Ds18b20 = 100                                         'Время ожидания допуска таймера

Config 1wire = Portd.4                                      'Порт подключения датчика DS18B20

Config Timer0 = Timer , Prescale = 64                       ' , Clear Timer = 0

Dim Byteds(9) As Byte                                       'Массив данных из DS18B20

Dim Segment1 As Byte                                        'Переменная Сегменты разряда 1
Dim Segment2 As Byte                                        'Переменная Сегменты разряда 2
Dim Segment3 As Byte                                        'Переменная Сегменты разряда 3

Dim Element_number As Byte                                  'Переменная текущег активного индикатора
Dim Status As Byte                                          'Переменная контроля ошибок наличия датчика
Dim Znak As Byte                                            'Переменная знака температуры
Dim Dot As Byte                                             'Переменная десятичной точки

Dim T0 As Byte                                              'Десятая часть температуры
Dim T1 As Byte                                              'Целая часть температуры

Dim Number1 As Byte                                         'Переменна значение сегмента 1
Dim Number2 As Byte                                         'Переменна значение сегмента 2
Dim Number3 As Byte                                         'Переменна значение сегмента 3

Segments Alias Portb                                        'Весь PortB называем  Segments
Element1 Alias Portd.0                                      'Порт Элемента 1
Element2 Alias Portd.1                                      'Порт Элемента 2
Element3 Alias Portd.2                                      'Порт Элемента 3
Dotpoint Alias Portd.3                                      'Порт десятичной точки
Check Alias Portd.6                                         'Порт индикатор-моргунчик

Declare Sub Refresh()                                       'Функция индикации
Declare Sub Look_timer()                                    'Функция ожидания
Declare Sub Onesegment()                                    'Функция двух сегментов один
Declare Sub Twosegment()                                    'Функция двух сегментов два

On Timer0 Refresh                                           'Вызов функции индикации по прерыванию
Enable Timer0                                               'Разрешаем TIMER0
Enable Interrupts                                           'Разрешаем прерывания глобально

Dot = 1                                                     'Точка при инициализации 0 - горит, 1 - погашен

'===============================================================================

Do
   If Status = 1 Then                                       'Опрос температуры только при отутствии ошибок датчика
      Check = 0                                             'Зажигаем индикатор-моргунчик
      Gosub Look_timer                                      'Ожидаем допуск от таймера
      1wreset                                               'Сбрасываем линию
      Gosub Look_timer                                      'Ожидаем допуск от таймера
      1wwrite &HCC                                          'Пропуск ПЗУ
      1wwrite &HBE                                          'Читаем из ОЗУ, чего мы там наизмеряли

      Byteds(1) = 1wread(9)                                 'Чтение 9 байт из датчика в массив

      If Byteds(9) = Crc8(byteds(1) , 8) Then               'Проверка контрольной суммы.

         If Byteds(2) > 248 Then                            'Проверка на отрицательность температуры
            Byteds(1) = &HFF - Byteds(1)                    'Высчитываем младший байт
            Byteds(2) = &HFF - Byteds(2)                    'Высчитываем старший байт
            Znak = 0                                        'Отрицательная температура '-'
         Else                                               'иначе, положительная
            Znak = 1                                        'Положительная температура ' '
         End If

         T0 = Byteds(1) And &B00001111                      'Берём от млачшего байта 4 последних разряда
         T0 = T0 * 6                                        'Вместо 0,0625 просто умножани на 6 и
         T0 = T0 / 10                                       'Делим на 10. получаем число от 0 до 10

         Byteds(1) = Byteds(1) / 16                         'Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
         Byteds(2) = Byteds(2) * 16                         'Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)
         T1 = Byteds(1) + Byteds(2)                         'Формируем результат для вывода на индикатор

         If Znak = 1 Then                                   'Если температура положительная
            If T1 >= 100 Then                               'Если температура больше или равна 100
               Number1 = 1                                  'Первый разряд присваиваем 1
               T1 = T1 - 100                                'Оставляем два разряда от числа 100
               Gosub Twosegment                             'Вызываем функцию обработки второго и третьего разрядов
               Dot = 1                                      'Точка выключена
            Elseif T1 <= 99 And T1 >= 10 Then               'Если температура от 99 до 10 включительно
               Number1 = T1 / 10                            'Высчитываем первый разряд
               Gosub Onesegment                             'Вызываем функцию обработки второго и третьего разрядов
               Dot = 0                                      'Точка ВКЛЮЧЕНА
            Else                                            'Если температура меньше 10 и до 0
               Number1 = 13                                 'Если температура меньше 10, то гасим первый разряд
               Gosub Onesegment                             'Вызываем функцию обработки второго и третьего разрядов
               Dot = 0                                      'Точка ВКЛЮЧЕНА
            End If
         Else                                               'Если температура отрицательная
            Number1 = 12                                    'Первый разряд "зажигаем минус"
            If T1 <= 9 Then                                 'Если температура от -0 до -9
               Gosub Onesegment                             'Вызываем функцию обработки второго и третьего разрядов
               Dot = 0                                      'Точка ВКЛЮЧЕНА
            Else                                            'Если температура от -10 и ниже(ниже холоднее)
               Gosub Twosegment                             'Вызываем функцию обработки второго и третьего разрядов
               Dot = 1                                      'Точка выключена
            End If
         End If

      Else                                                  'Если не сошлась контрольная сумма
         Number1 = 14                                       'c
         Number2 = 11                                       'r
         Number3 = 14                                       'c
         Status = 0                                         'Ставим статус 0 в случае ошибки
         Dot = 1                                            'Точка выключена
      End If

      Check = 1                                             'Гасим индкатор-моргунчик
   End If

   Gosub Look_timer                                         'Ожидаем допуск от таймера
   1wreset                                                  'Сбрасываем линию
   Gosub Look_timer                                         'Ожидаем допуск от таймера
   1wwrite &HCC                                             'Пропуск ПЗУ
   1wwrite &H44                                             'Запускаем преобразование

   If Err = 1 Then                                          'Если ответа небыло, выводим сообщение об ошибке Err
      Number1 = 10                                          'E
      Number2 = 11                                          'r
      Number3 = 11                                          'r
      Status = 0                                            'Ставим статус 0 в случае ошибки
      Dot = 1                                               'Точка выключена
   Else
      Status = 1                                            'Ставим статус 1 если всё хорошо, для опроса датчика
   End If

   Segment1 = Lookup(number1 , Select_number)               'Присваивание сегментам значений из Select_Number
   Segment2 = Lookup(number2 , Select_number)               'Присваивание сегментам значений из Select_Number
   Segment3 = Lookup(number3 , Select_number)               'Присваивание сегментам значений из Select_Number

   Waitms 1500                                              'Ожидаем 1500 миллисекунд

Loop
'===============================================================================

'ФУНКЦИЯ ВЫВОДА ДВУХ СЕГМЕНТОВ
Onesegment:
   Number2 = T1 Mod 10                                      'Обработка второго разряда
   Number3 = T0                                             'Обработка третьего разряда
Return
'END ФУНКЦИЯ ВЫВОДА ДВУХ СЕГМЕНТОВ


'ФУНКЦИЯ ВЫВОДА ДВУХ СЕГМЕНТОВ
Twosegment:
   Number2 = T1 / 10                                        'Обработка второго разряда
   Number3 = T1 Mod 10                                      'Обработка третьего разряда
Return
'END ФУНКЦИЯ ВЫВОДА ДВУХ СЕГМЕНТОВ


'ФУНКЦИЯ ОЖИДАНИЯ
Look_timer:
   Do
      nop                                                   'Пустой цикл
   Loop Until Tcnt0 < Ds18b20                               'Пока таймер не станет 100 и более
Return
'END ФУНКЦИЯ ОЖИДАНИЯ


'ВЫВОДИМ ПЕРЕМЕННЫЕ НА ИНДИКАТОР ПО ТАЙМЕРУ
Refresh:
   If Element_number = 1 Then                               'Если активный индикатор 1
      Element1 = 1                                          'Гасим индикатор 1
      Element2 = 1                                          'Гасим индикатор 2
      Element3 = 1                                          'Гасим индикатор 3
      Segments = Segment1                                   'Передаём сегменты в индикатор
      Element1 = 0                                          'Зажигаем индикатор 1
      Element_number = 2                                    'Переход на индикатор 2 в следующим цикле
   Elseif Element_number = 2 Then                           'Если активный индикатор 2
      Element1 = 1                                          'Гасим индикатор 1
      Element2 = 1                                          'Гасим индикатор 2
      Element3 = 1                                          'Гасим индикатор 3
      Segments = Segment2                                   'Передаём сигменты в индикатор
      Element2 = 0                                          'Зажигаем индикатор 2
      Element_number = 3                                    'Переход на индикатор 3 в следующим цикле
      Dotpoint = Dot                                        'Зажигать или не зажигать точку
   Else                                                     'Если активный индикатор 3
      Element1 = 1                                          'Гасим индикатор 1
      Element2 = 1                                          'Гасим индикатор 2
      Element3 = 1                                          'Гасим индикатор 3
      Segments = Segment3                                   'Передаём сигменты в индикатор
      Element3 = 0                                          'Зажигаем индикатор 3
      Dotpoint = 1                                          'Точка не горит
      Element_number = 1                                    'Переход на индикатор 1 в следующим цикле
   End If
Return
'END ВЫВОДИМ ПЕРЕМЕННЫЕ НА ИНДИКАТОР ПО ТАЙМЕРУ


'МАССИВ ДАННЫХ СЕГМЕНТОВ
Select_number:
   Data &B00001000                                          '0  - 0
   Data &B01011011                                          '1  - 1
   Data &B00010100                                          '2  - 2
   Data &B00010001                                          '3  - 3
   Data &B01000011                                          '4  - 4
   Data &B00100001                                          '5  - 5
   Data &B00100000                                          '6  - 6
   Data &B00011011                                          '7  - 7
   Data &B00000000                                          '8  - 8
   Data &B00000001                                          '9  - 9
   Data &B00100100                                          'E  - 10
   Data &B01110110                                          'r  - 11
   Data &B01110111                                          '-  - 12
   Data &B01111111                                          ' ' - 13
   Data &B01110100                                          'c' - 14
'END МАССИВ ДАННЫХ СЕГМЕНТОВ'


Да, есть что поправить в коде, но сейчас работает, и работает стабильно на температурах до +95 , только датчики дохнут при +95 и выше и длительном использовании

в коде суть динамической индикации и опроса DS18b20 без взаимных помех

0

9

По датащам вроде как 125 градусов должны выдерживать...
У меня один датчик много и часто кипятится в баке и вроде живой  :D

0

10

Леoнид написал(а):

и работает стабильно на температурах до +95 , только датчики дохнут при +95 и выше и длительном использовании

Сейчас имеющиеся задержки - только для работы самого датчика.

Сделайте опрос датчика пореже, один раз в секунду - маловато.
Он банально перегревается... ;)

0

11

замудрёно......

0

12

kip написал(а):

замудрёно......

Поддежриваю.

0

13

kip написал(а):

замудрёно......

Вариант по проще, примерно с тем же функционалом. Терморегуляторы

0

14

О, Саша появился! :cool:  А я аж за переживал, мож случилось чего. (по правде, без сарказма)

0

15

А чего замудрёного то?
не один день потратил пока избавился от переодического "подрыгивания" динамической индикации. Так вроде и не заметно, чуть чуть совсе, а боковое зрение выхватывает. Да и 64% памяти используется. и переменные типа BYTE для индикации десятых градуса. Да и не Atmega8, а Tiny2313. И индикация на трёх семисегментниках. Да, в протеусе оно работает, а вот в готовом проекте были вопросы. Можно и на Сях было писать, но не знаю я Си ))), да и баском не знаю - читал, изучал, пробовал, эксперементировал.
Взял бы чей то готовый проект, но как ни искал - везде были подрыгивания при индикации, или мерцания. Прверял в железе и не устраивали чужие проекты.
И  0,0625 градуса считет без введения плавающей точки, хоть погрешность дотчика 0.5 градуса

Вот  если есть спец то подскажите как такой глюк убрать -  через непонятные промежутки вемени выпадает ошибка индикации "crc" - как не ловил систему - не выявил. может месяц нормально,а может за день 5 раз по 2-3 минуты выскативать. Рассматривал вариант помехи внешней, т.к. выпадает на всех устройствах сразу. А включаются все приборы контроля температуры все вместе, может с таймерами и прерываниями намудрил чего, хотя там и мудрить то особо нечего.

Про датчик DS18B20. Тот что в железной колбе с черным проводом и 3 проводами на выходе - лажа, 100 -115 градусов и даже уплотнительную ?эпоксидную? смолу из железной гильзы выдавливает. А сам датчик или перегревается или его пластиковое содержимое давлением ломает. Про опрос раз в 1.5 секунду - на температуре 100 градусов - не сильно он себе температуру повысит таким опросом, а при 115 и вообще искажения будут минимальны и не принципиальны в моём котле.

А ещё сталкивался с датчиками с предустановленной битностью в 9 бит, не 12. Не мог поять с чего это десятые пропадали, и были кратны не 0.1 а 0.5
Добавлялся код при первом запуске

Код:
'1wreset                                                     'Сбрасываем линию
'1wwrite &HCC                                                'Пропуск ПЗУ
'1wwrite &H4E                                                'Команда на записть в ОЗУ 3 байт
'1wwrite &H00                                                '
'1wwrite &H00                                                '
'1wwrite &H7F                                                'Устанавливаем разрядность 12 бит

'1wreset                                                     'Сбрасываем линию
'1wwrite &HCC                                                'Пропуск ПЗУ
'1wwrite &H48                                                'Копирование из ОЗУ в EEPROM
'Waitms 1500


Это позволяет повысить разрядность, может и не надо, но мне хотелось )))

0

16

Леoнид написал(а):

через непонятные промежутки времени выпадает ошибка индикации "crc"


Работа с шиной 1wire основана на таймингах, поэтому довольно чувствительна к прерываниям. Используйте аппаратный 1wire, или симулируйте его-же, средствами МК.

читайте ЛС

Примеры здесь и здесь

Исследование Ds18b20 (датчик температуры)
http://bascomavr.3bb.ru/viewtopic.php?id=1129#p22596
Библиотека для аппартаного модуля 1Wire на основе USART
http://bascomavr.3bb.ru/viewtopic.php?id=1503#p17079

Отредактировано sasha_1973 (2018-02-23 04:17:58)

+1

17

Вот если использовать ваш алгоритм, если хотите во всём разобраться, то пару советов.
В место

Код:
'ФУНКЦИЯ ОЖИДАНИЯ
Look_timer:
   Do
      nop                                                   'Пустой цикл
   Loop Until Tcnt0 < Ds18b20                               'Пока таймер не станет 100 и более
Return

Выставляйте флаг в подпрограмме прерывания, а в основной программе ждите его, и только после флага общайтесь с датчиком.

Код:
 Gosub Look_timer                                         'Ожидаем допуск от таймера
   1wreset                                                  'Сбрасываем линию

будет так:

Код:
reset Flag
bitwait flag, set
1wreset

кроме того, в прерывании можно сохранять только нужные регистры, что сильно сократит время и объём программы (для 2313 это довольно существенно)
Потом, вывод динамической индикации и расчёт температуры уже жёван и пережёван. Более экономичный.
и ещё
- у вас же не ядерный котёл, что бы так часто замерять температуру.
- вообще, через месяц вы вообще не будете замечать мерцания. Ну это так,от себя.

Отредактировано kip (2018-02-23 09:26:00)

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » DS18B20 задержки