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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Терморегулятор инкубатора с доп. каналом и поворотом яиц.


Терморегулятор инкубатора с доп. каналом и поворотом яиц.

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

1

Делюсь разработанным терморегулятором для инкубатора. Принцип - релейный - достигла заданная температура - нагрузка щелкает раз в пол секунды вкл/выкл. Полезла температура выше - нагрузка отключилась, упала ниже заданной - нагрузка включилась. Чтобы нагрузка не щелкала достаточно закомментировать строку "If Viv_peremennaya(1) = Booton(1) And Portc.1 = 1 Then : Reset Portc.1 : Elseif Viv_peremennaya(1) = Booton(1) And Portc.1 = 0 Then : Set Portc.1 : End If  "
Отдельно сделан канал для поворота яиц. Яйца переворачиваются двигателем в течении 15 секунд (эти секунды жестко заданы в программе и кнопками не регулируются) через заданный интервал времени.
Всего 4 кнопки - две задают температуру и две интервал времени между переворотами яиц.
Индикаторы отображают десятые градуса. При отрицательных температурах появляется знак минус. При температуре ниже чем 9,9 градуса десятые не отображаются. Например -9,9 а ниже -10. Обновление температур обоих индикаторов проходит меньше чем за секунду.
Разработка не претендует на научный прорыв, но зато можно посмотреть как организовано измерение, старался избежать ошибок во время измерений, поэтому добавлена проверка CRC от DS18B20 и каждый датчик подключен к своей лапе МК. Для повышения надежности задействован сторожевой таймер.

После включения устройства оно сразу начинает работать. Необходимо кнопками задать температуру и интервал времени. Данные хранятся в EEPROM.
Первый канал отображает температуру на индикаторе и выполняет регулирование температуры. Второй канал для визуального контроля. Он просто показывает температуру.
Fuse биты не помню.

Код:
'Автор Авраменко Павел.
'e-mail p-a-h-a@yandex.ru
'youtube http://www.youtube.com/c/Happinesstoom
$regfile = "m8def.dat"                                      ' говорим компилятору что у нас микропроцессор Atmega 8
$crystal = 8000000                                          ' говорим компилятору что процессор тактируется от генератора с частотой 8, 000 000 мегагерц
Ddrb = &B00111111 : Ddrd = &B11111111 : Ddrc = &B00000011 : Portc = &B11111101
Dim W As Byte , I As Byte , Chislo(6) As Integer , Viv_peremennaya(2) As Integer , Temp_print(2) As Integer , Booton(2) As Integer , Settemp(2) As Eram Integer , Dp(2) As Byte , Секунды As Integer , Минуты As Integer , Время_задержки As Integer , Время_задержки_епром As Eram Integer
Dim Temp As Integer , Температура As Single , Готовая_температура_str As String * 10 , Ответ_датчика_ds18b20(9) As Byte At Temp Overlay , Ошибка_измерения As Bit , Номер_пина As Byte , Округление As Integer
Declare Sub Приостановить_таймер0
Config Watchdog = 2048 : Start Watchdog                     ' конфигурация сторожевого таймера
Config 1wire = Portb.6 : Config 1wire = Portb.7             'порт, куда садим ногами два датчика типа ds18b20 ПО ДВУХПРОВОДНОЙ СХЕМЕ. ЦЕНТРАЛЬНЫЙ СЮДА С ПОДТЯЖКОЙ 1 КОМ НА +, А ДВА КРАЙНИХ СОЕДИНИТЬ ВМЕСТЕ И НА МИНУС
Config Timer0 = Timer , Prescale = 64 : On Timer0 Pulse :   ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer2 = Timer , Prescale = 1024 : On Timer2 Bootons :       ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer , Prescale = 256 : On Timer1 Отсчет_времени
Enable Timer0 : Enable Timer1 : Enable Timer2 : Enable Interrupts
Chislo(6) = 0 : Chislo(5) = 16 : Chislo(4) = 16 : Chislo(3) = 12 : Chislo(2) = 15 : Chislo(1) = 10       ' приветствие HELLO
If Settemp(1) < 1000 Or Settemp(1) > 0 Then : Booton(1) = Settemp(1) : Else : Settemp(1) = 375 : Booton(1) = Settemp(1) : End If       ' проверка данных eeprom
If Время_задержки_епром < 1000 Or Время_задержки_епром > 0 Then : Время_задержки = Время_задержки_епром : Booton(2) = Время_задержки : Else : Время_задержки = 180 : Время_задержки_епром = 180 : Booton(2) = Время_задержки : End If       ' проверка данных eeprom
'======================основной цикл программы==================================
 Do
  Reset Watchdog
  For Номер_пина = 6 To 7
    Gosub Запуск_измерения
    Reset Watchdog
  Next
  Waitms 750                                                ' И ждём, пока померяется
  For Номер_пина = 6 To 7
    Gosub Опрос_ds18b20
    If Ошибка_измерения = 0 Then : Viv_peremennaya(номер_пина - 5) = Температура : Set Dp(1) : Set Dp(2) : Gosub Vicisleniya : End If : Ошибка_измерения = 0       ' Если измерение без ошибок то идем на подпрограмму разбития температуры на сегменты
    Reset Watchdog                                          ' сброс сторожевого таймера
    If Viv_peremennaya(1) > Booton(1) Then Reset Portc.1 : If Viv_peremennaya(1) < Booton(1) Then Set Portc.1
    If Viv_peremennaya(1) = Booton(1) And Portc.1 = 1 Then : Reset Portc.1 : Elseif Viv_peremennaya(1) = Booton(1) And Portc.1 = 0 Then : Set Portc.1 : End If
    If Минуты >= Время_задержки Then : Reset Portc.0 : Секунды = 0 : Минуты = 0 : End If : If Секунды >= 15 Then Set Portc.0       ' управление поворотом яиц
  Next
 Loop
End
'===============================================================================
Запуск_измерения:
 Stop Timer0 : Reset Portb.w
    1wreset Pinb , Номер_пина : Приостановить_таймер0       ' Занимаем шину 1Ware
    1wwrite &HCC , 1 , Pinb , Номер_пина : Приостановить_таймер0       ' Обращение ко всем датчикам
    1wwrite &H44 , 1 , Pinb , Номер_пина                    ' Запуск измерения всех датчиков
Set Portb.w : Start Timer0
Return
'===============================================================================
Опрос_ds18b20:
Stop Timer0 : Reset Portb.w
    1wreset Pinb , Номер_пина : Приостановить_таймер0       ' Занимаем шину 1Ware
    1wwrite &HCC , 1 , Pinb , Номер_пина : Приостановить_таймер0       ' Адресное обращение к Ds18b20
    1wwrite &HBE , 1 , Pinb , Номер_пина : Приостановить_таймер0       ' Команда чтения ОЗУ датчика
    Ответ_датчика_ds18b20(1) = 1wread(9 , Pinb , Номер_пина)       ' Принимаем 8 байт данных + 1 байт контрольной суммы которые кладутся в переменную Temp
Set Portb.w : Start Timer0
    If Err = 0 Then                                         ' Если получили ответ датчика
         If Ответ_датчика_ds18b20(9) = Crc8(ответ_датчика_ds18b20(1) , 8) Then : Температура = Temp : Shift Температура , Right , 4 : Температура = Температура * 10 : Else : Set Ошибка_измерения : End If       ' Проверяем контрольную сумму полученных данных ' Получаем сырые данные с Ds18b20 ' Получаем готовое значение температуры с знаком
    Else : Set Ошибка_измерения : End If                    ' если датчик не откликнулся ставим метку ошибки
Return
'===============================================================================
Vicisleniya:                                                ' разбиваем трехзначную температуру на два числа
 For I = 1 To 2
 Temp_print(i) = Abs(viv_peremennaya(i))                    ' берем модуль температуры для отображения положительного значения. Минус подставим позже
 If Viv_peremennaya(i) < 0 And Temp_print(i) >= 100 Then : Округление = Temp_print(i) Mod 10 : Temp_print(i) = Temp_print(i) / 10 : If Округление > 4 Then Incr Temp_print(i) : Reset Dp(i) : End If       'Округление при минус 10 и выше и убирание последнего разряда
 Next
 Stop Timer0 : Reset Portb.w
 For I = 3 To 1 Step -1
  Chislo(i + 3) = Temp_print(2) Mod 10                      ' заносим в масив последнюю цифру от числа Temp_print(12345678 mod 10 = 8)
     Temp_print(2) = Temp_print(2) / 10                     ' отсекаем последнюю цифру от числа Temp_print (12345678/10=1234567)
  Chislo(i) = Temp_print(1) Mod 10                          ' заносим в масив последнюю цифру от числа Temp_print(12345678 mod 10 = 8)
     Temp_print(1) = Temp_print(1) / 10                     ' отсекаем последнюю цифру от числа Temp_print (12345678/10=1234567)
 Next
 If Viv_peremennaya(1) = 1000 Then : For I = 1 To 3 : Chislo(i) = 10 : Next : Elseif Viv_peremennaya(2) = 1001 Then : For I = 4 To 6 : Chislo(i) = 10 : Next : End If       ' гасим три символа в случае когда переменная равна метке 1000 или 1001
 If Chislo(1) = 0 Then Chislo(1) = 10 : If Chislo(4) = 0 Then Chislo(4) = 10       ' УБИРАЕМ НОЛИ ПЕРЕД ЧИСЛОМ ЧТОБ БЫЛО НЕ 02,1 А 2,1
 If Viv_peremennaya(1) < 0 Then Chislo(1) = 11 : If Viv_peremennaya(2) < 0 Then Chislo(4) = 11       ' СТАВИМ МИНУС В НАЧАЛЕ, ЕСЛИ ТЕМПЕРАТУРА ОТРИДЦАТЕЛЬНАЯ
 Set Portb.w : Start Timer0
Return
'===============================================================================
Sub Приостановить_таймер0:
Set Portb.w : Start Timer0 : Waitms 50 : Stop Timer0        ' гасим семисегментник, останавливаем таймер и через 50 мсек все включаем
End Sub
'===============================================================================
Pulse:                                                      ' подпрограмма прерываний таймера0 для работы с семисегментником
   Reset Portb.w                                            ' трогаем порты только с 0 по 5
   Incr W : If W > 5 Then W = 0                             ' При каждом срабатывании таймера выбираем какой сегмент будем показывать от 0,1,2,3
   Portd = Lookup(chislo(w + 1) , Chisla)                   'таблица DTA начинает считатся с первой ячейки. А поскольку значение времени может быть 0 то прибавляем единицу. Х сейчас равен 1 поэтому берем масив Х+1 т.е cifri(2). Выше мы считали что Cifri(2) = _min / 10 и это = 5 а поскольку тут мы прибавили 1 то берем шестой элемент таблицы DTA который выведет на семисегментник цифру 5. (когда дойдем до часов и нужно будет отобразить 0 (Cifri(4) = _hour / 10) то выберется элемент таблицы с порядковым номером 0+1=1 т.е первый элемент &HEF.
   Set Portb.w                                              'поскольку индикатор у меня подключен с общим минусом то выше мы его погасили подав на все общие провода плюс ( логическую единицу в строкеPortb = &HFF) теперь мы зажигаем сегмент с порядковым номером Х который сейчас равен 1
   If W = 1 And Dp(1) = 1 Then Reset Portd.2
   If W = 4 And Dp(2) = 1 Then Reset Portd.2
Return
'===============================================================================
Chisla:
 '     0     1     2     3    4    5    6    7    8    9   10""  11-   12E  13r  14o   15H  16L
 Data 20 , 215 , 140 , 133 , 71 , 37 , 36 , 151 , 4 , 5 , 255 , 239 , 44 , 238 , 228 , 70 , 124

'A Alias Portd.6 : B Alias Portd.5 : C Alias Portd.3 : D Alias Portd.1 : E Alias Portd.0 : F Alias Portd.7 : G Alias Portd.4 : Dp Alias Portd.2       'Тут вписываем порты к которым подключены сегменты индикатора
'Dig1 Alias Portb.5 : Dig2 Alias Portb.4 : Dig3 Alias Portb.3 : Dig4 Alias Portb.2 : Dig5 Alias Portb.1 : Dig6 Alias Portb.0       ' тут вписываем порты к которым подключены общие провода каждой цифры
'===============================================================================
Отсчет_времени:
Timer1 = 34797                                              ' корекция для того чтоб таймер работал раз в секунду или 34285
Incr Секунды : If Секунды = 60 Then : Incr Минуты : Секунды = 0 : End If
Return
'===============================================================================
Bootons:
Enable Interrupts
Stop Timer1
Debounce Pinc.2 , 0 , Temperatura1 , Sub
Debounce Pinc.3 , 0 , Temperatura2 , Sub
Debounce Pinc.4 , 0 , Время1 , Sub
Debounce Pinc.5 , 0 , Время2 , Sub
Start Timer1
Return
'===============================================================================
Temperatura1:
Do
Set Dp(1) : Reset Dp(2)
If Booton(1) < 1 Then Booton(1) = 1
Decr Booton(1)
Viv_peremennaya(1) = Booton(1)
Viv_peremennaya(2) = 1001
Gosub Vicisleniya
Waitms 100
Reset Watchdog
Loop Until Pinc.2 = 1
Start Timer1
Wait 1
Reset Watchdog
Settemp(1) = Booton(1)
Settemp(2) = Booton(2)
Return
'===============================================================================
Temperatura2:
Do
Set Dp(1) : Reset Dp(2)
Incr Booton(1) : If Booton(1) > 999 Then Booton(1) = 999
Viv_peremennaya(1) = Booton(1)
Viv_peremennaya(2) = 1001
Gosub Vicisleniya
Waitms 100
Reset Watchdog
Loop Until Pinc.3 = 1
Start Timer1
Wait 1
Reset Watchdog
Settemp(1) = Booton(1)
Return
'===============================================================================
Время1:
Do
Reset Dp(2) : Reset Dp(1)
If Booton(2) < 1 Then Booton(2) = 1
Decr Booton(2)
Viv_peremennaya(1) = 1000
Viv_peremennaya(2) = Booton(2)
Gosub Vicisleniya
Waitms 100
Reset Watchdog
Loop Until Pinc.4 = 1
Start Timer1
Wait 1
Reset Watchdog
Время_задержки = Booton(2)
Время_задержки_епром = Время_задержки
Return
'===============================================================================
Время2:
Reset Dp(2) : Reset Dp(1)
Do
Incr Booton(2) : If Booton(2) > 999 Then Booton(2) = 999
Viv_peremennaya(1) = 1000
Viv_peremennaya(2) = Booton(2)
Gosub Vicisleniya
Waitms 100
Reset Watchdog
Loop Until Pinc.5 = 1
Start Timer1
Wait 1
Reset Watchdog
Время_задержки = Booton(2)
Время_задержки_епром = Время_задержки
Return
'===============================================================================

http://s6.uploads.ru/t/d1Tzp.jpg

Отредактировано Pasha (2016-11-22 01:13:44)

0

2

Подскажите сразу по Fuse битам, не помню, нужно ли их менять для:
Config Watchdog = 2048 : Start Watchdog
?
Конструкция уже несколько месяцев работает в далеке от меня.

Отредактировано Pasha (2016-11-22 01:15:12)

0

3

нет

0


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Терморегулятор инкубатора с доп. каналом и поворотом яиц.