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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Фотореле. Сумеречный выключатель


Фотореле. Сумеречный выключатель

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

1

ПРивет всем. Собрал Устройство сумеречного переключателя. Аналог УТФР-Ц. Себестоимость обошлась вдвое меньше.
Управление: кн. УСТ - режим выбора уставок, на каждый режим выведены подсказки: ON, OFF, Lig.
В исходном режиме индикация текущего уровня освещенности 0..100%. Уставки сохраняются в EEPROM, при первом включении ON = 40, Off = 50.
Осуществлена блокировка уставок - уставка ON не может быть больше уставки OFF. Это чтобы днем свет не включался, при неправильной настройке. В случае ошибки, устройство выдает мигающую подсказку Err. После этого возвращает значение ВВОДИМОЙ уставки из EEPROM. В принципе все  :dontknow:


Код:
'*******************************************************************************
'* Filename    : Сумеречный выключатель                                                                                    *
'* Revision    : 1.0                                                                                                                        *
'* Controller  : ATMEGA8                                                                                                               *
'* Compiler    : BASCOM-AVR 1.11.9.0                                                                                           *
'* Author      : MACTEPOK                                                                                                             *
'************************************************************************************
$regfile = "m8def.dat"                                      'определяем контроллер
$crystal = 4000000                                          'внутренний генератор
'$sim
$lib "mcsbyte.lbx"                                          'подключаем библиотеку функций

Config Pinc.0 = Input : Portc.0 = 1                         'кнопка УСТ
Config Pinc.1 = Input : Portc.1 = 1                         'кнопка Вверх
Config Pinc.2 = Input : Portc.2 = 1                         'кнопка Вниз


Config Portd = Output : Config Portb = Output               'порты на выход к которым подключен индикатор
Load1 Alias Portb.3                                         'нагрузка №1
Config Adc = Single , Prescaler = 8 , Reference = Avcc      'настраиваем АЦП

Dim W As Byte : Dim Y As Byte : Dim X As Byte : Dim I As Byte : Dim Z As Byte : Dim Chislo(8) As Integer : Dim Light As Integer : Dim Light_on As Byte : Dim Light_off As Byte : Dim Sostoyanie As Byte : Dim Copy_print As Integer : Dim _print As Integer : Dim Pokazaniya As Integer : Dim View_menu As Byte
Dim On_flag As Bit                                          'флаг режима настройки уставки ON
Dim Off_flag As Bit                                         'флаг режима настройки уставки OFF
Dim Set_flag As Bit                                         'флаг режима меню
Dim Podskaz_flag As Bit                                     'флаг режима отображения подсказки

A Alias Portd.0 : B Alias Portd.1 : C Alias Portd.2 : D Alias Portd.3       'порты, к которым подключены сегменты индикатора
E Alias Portd.4 : F Alias Portd.5 : G Alias Portd.6         '
Dig1 Alias Portb.0 : Dig2 Alias Portb.1 : Dig3 Alias Portb.2       '  порты, к которым подключены общие провода каждой цифры
For X = 1 To 3                                              ' присваиваем всем цифрам пустоту, чтоб в момент включения не высвечивались ноли
Chislo(x) = 11
Next

Config Timer0 = Timer , Prescale = 8 : On Timer0 Pulse      ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer , Prescale = 1 : On Timer1 Bootons    ' конфигурируем таймер 1 и назначаем подпрограмму которая выполняется при переполнении таймера
Enable Interrupts : Enable Timer0 : Enable Timer1           ' разрешаем прерывания, таймер 0,   таймер 1
Start Timer0 : Start Timer1
   Readeeprom Light_on , 0                                  ' Считываем из EEPROM уставку ON
   Readeeprom Light_off , 5                                 ' Считываем из EEPROM уставку OFF
   If Light_off = 255 Then Light_off = 50                   ' При первом включении, когда в EEPROM пусто, задаем начальные уставки
   If Light_on = 255 Then Light_on = 40
   Start Adc

Do
   Stop Timer0
   If X > 8 Then
      Light = Getadc(5)                                     'опрос фоторезистора
      Light = Light / 10                                    'пересчет
'      Light = Light - 10
      If Light > 100 Then Light = 100
   X = 0                                                    ' чтобы показания не скакали
   End If
   Start Timer0
   If Light <= Light_on Then Sostoyanie = 1                 'если освещенность ниже уставки ON, то включаем нагрузку
   If Light >= Light_off Then Sostoyanie = 0                'если освещенность выше уставки OFF, то выключаем нагрузку
   If Sostoyanie = 1 Then : Set Load1 : Else : Reset Load1 : End If
Loop

'*******************************************************************************
' Индикация
Pulse:
   Stop Timer0                                              'останавливаем таймер 0
   _print = Light                                           'запись показаний  освещенности на индикатор
   If On_flag = 1 Then _print = Light_on                    'если режим настройки уставки ON,то на индикатор уставку ON
   If Off_flag = 1 Then _print = Light_off                  'если режим настройки уставки OFF,то на индикатор уставку OFF

   If Podskaz_flag = 0 Then                                 'если не выводим на индикатор подсказки, то работаем с числами
      Copy_print = _print                                   'скопируем переменную до обработки

         For I = 1 To 3                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print Mod 10                          ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print = _print / 10                               ' отсекаем последнюю цифру от числа Temp_print (123/10=12)
      Next
      If Copy_print < 100 Then Chislo(3) = 11               'если  переменная < 100, то устанавливаем в 3м индикаторе пустоту
      If Copy_print < 10 Then Chislo(2) = 11                ' если  переменная < 10, то устанавливаем в 2м индикаторе пустоту
   End If


   Reset Dig1 : Reset Dig2 : Reset Dig3
   Incr W : If W > 4 Then W = 1                             ' выбираем какую цифру сейчас включать
   Y = 0
   Gosub Look : A = Z                                       ' переходим к подпрограмме Look, которая определяет нужно ли сейчас загорется сегменту А
   Gosub Look : B = Z
   Gosub Look : C = Z
   Gosub Look : D = Z
   Gosub Look : E = Z
   Gosub Look : F = Z
   Gosub Look : G = Z

   Select Case W                                            ' включаем цифру которую выбрали (w). Подаем плюс на общий провод конкретной цифры
      Case 1 :
         Set Dig1
      Case 2 :
         Set Dig2
      Case 3 :
         Set Dig3
   End Select
   Start Timer0
Return
'
Look:                                                       ' подпрограмма которая определяет нужно ли сейчас гореть сегменту, который вызвал эту подпрограмму
   Z = Chislo(w) * 7 : Z = Y + Z                            ' определяем порядковый номер числа из таблици DATA. W - это цифра которую будем выводить 1..2..3, Y это номер сегмента (A=0 B=1 C=2...G=7)
   Z = Lookup(z , Cifri)                                    ' выбираем из таблици включить или выключить нужный сегмент
   Incr Y                                                   'Y это номер сегмента (A=0 B=1 C=2...). Chislo(w) * 7 - переход на начало нужной строки Data.Z = Y + Z - по очереди перебираем сегменты в строке.
Return
'
Cifri:
' таблица сегментом для индикаторов с общим плюсом      |Chislo(i)| Символ |
Data 0 , 0 , 0 , 0 , 0 , 0 , 1                              '0
Data 1 , 0 , 0 , 1 , 1 , 1 , 1                              '1
Data 0 , 0 , 1 , 0 , 0 , 1 , 0                              '2
Data 0 , 0 , 0 , 0 , 1 , 1 , 0                              '3
Data 1 , 0 , 0 , 1 , 1 , 0 , 0                              '4
Data 0 , 1 , 0 , 0 , 1 , 0 , 0                              '5
Data 0 , 1 , 0 , 0 , 0 , 0 , 0                              '6
Data 0 , 0 , 0 , 1 , 1 , 1 , 1                              '7
Data 0 , 0 , 0 , 0 , 0 , 0 , 0                              '8
Data 0 , 0 , 0 , 0 , 1 , 0 , 0                              '9
Data 1 , 1 , 1 , 1 , 1 , 1 , 0                              '10           "-"
Data 1 , 1 , 1 , 1 , 1 , 1 , 1                              '11           ""
Data 1 , 1 , 1 , 0 , 0 , 0 , 1                              '12           "L"
Data 1 , 1 , 0 , 1 , 0 , 1 , 0                              '13           "n"
Data 0 , 1 , 1 , 1 , 0 , 0 , 0                              '14           "F"
Data 0 , 1 , 1 , 0 , 0 , 0 , 0                              '15           "E"
Data 1 , 1 , 1 , 1 , 0 , 1 , 0                              '16           "r"
Data 1 , 1 , 1 , 1 , 0 , 0 , 1                              '17           "I"
Data 0 , 0 , 0 , 1 , 1 , 0 , 0                              '18           "g"

'*******************************************************************************
'
'*******************************************************************************
' Опрос кнопок
Bootons:
   Incr X
   Stop Timer1
   Do
      If Pinc.0 = 0 Then Gosub Set_mode                     ' Нажатие кнопки УСТ
      Bitwait Pinc.0 , Set                                  'Ждем, пока отпустят кнопку УСТ
      If Set_flag = 1 Then                                  'Кнопки Вверх и Вниз активны только после входа в меню
         If Pinc.1 = 0 Then Gosub Up_const
         If Pinc.2 = 0 Then Gosub Down_const
      End If
   Loop Until View_menu = 0                                 'Опрос кнопок в бесконечном цикле, пока не выйдем из меню
   Enable Interrupts : Enable Timer0 : Start Timer0 : Start Timer1
Return
'*******************************************************************************
'
'
Set_mode:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Set Podskaz_flag                                         'Поднимаем флаг вывода подсказок (буквы)
   Incr View_menu                                           'пункты меню

   If Light_on >= Light_off Then Gosub Errors               'Блокировка ввода уставок. Чтобы свет включался только ночью!
   If View_menu >= 3 Then View_menu = 0

      Select Case View_menu
       Case 0 :                                             'показываем 'LIg' (Light)
           Chislo(1) = 6
           Chislo(2) = 17
           Chislo(3) = 12
           Reset Set_flag                                   'режим отображения текущего значения освещенности
           Reset On_flag                                    '
           Reset Off_flag
           Writeeeprom Light_off , 5
           Waitms 500


           Case 1 :                                         ' On
           Chislo(1) = 11
           Chislo(2) = 13
           Chislo(3) = 0
           Set Set_flag
           Set On_flag                                      'режим отображения уставки ON
           Reset Off_flag
           Waitms 500

           Case 2 :                                         ' OFF
           Chislo(1) = 14
           Chislo(2) = 14
           Chislo(3) = 0
           Set Set_flag
           Reset On_flag
           Set Off_flag                                     'режим отображения уставки OFF
           Writeeeprom Light_on , 0
           Waitms 500

           End Select

   Reset Podskaz_flag
Return
'
Errors:
   Chislo(1) = 16
   Chislo(2) = 16                                           'Выводим подсказку Err и мигаем
   Chislo(3) = 15
   Waitms 500
   Chislo(1) = 11
   Chislo(2) = 11
   Chislo(3) = 11
   Waitms 500
   Chislo(1) = 16
   Chislo(2) = 16
   Chislo(3) = 15
   Waitms 500
   Chislo(1) = 11
   Chislo(2) = 11
   Chislo(3) = 11
   Waitms 500

   If On_flag = 1 Then Readeeprom Light_on , 0              'Если были в 1 пункте меню, возвращаем прежнюю уставку ON из EEPROM
   If Off_flag = 1 Then Readeeprom Light_off , 5            'Если были во 2 пункте меню, возвращаем прежнюю уставку OFF из EEPROM
   Decr View_menu
Return
'
Up_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   If On_flag = 1 Then                                      'если в режиме отображения уставки ON
      Do
         Incr Light_on
         Waitms 50
         If Light_on >= 100 Then Light_on = 100
      Loop Until Pinc.1 = 1
   End If
   If Off_flag = 1 Then                                     'если в режиме отображения уставки OFF
      Do
         Incr Light_off
         Waitms 50
         If Light_off >= 100 Then Light_off = 100
      Loop Until Pinc.1 = 1
   End If
Return
'
'
Down_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   If On_flag = 1 Then                                      'если в режиме отображения уставки ON
      Do
         Decr Light_on
         Waitms 50
         If Light_on <= 1 Then Light_on = 1
      Loop Until Pinc.2 = 1
   End If
   If Off_flag = 1 Then                                     'если в режиме отображения уставки OFF
      Do
         Decr Light_off
         Waitms 50
         If Light_off <= 2 Then Light_off = 2
      Loop Until Pinc.2 = 1
   End If
Return

увеличить

увеличить

Отредактировано MACTEPok (2010-11-29 22:11:43)

0

2

В готовом виде.

увеличить

0

3

Здравствуйте. С интересом ознакомился со схемой сумеречного переключателя, по всей видимости, её можно применить не только в этом устройстве.
Я например, ищу схему цифрового манометра.
На основе Вашей схемы можно сделать такой цифровой манометр давления.
Попробовал просимулировать схему сумеречного переключателя в протеусе, стал понятен принцип её работы, несколько доработал схему для цифрового манометра, (см. схему в протеус) для датчика ММ393А, конструктивно он крепится на массу , (параметры датчика ММ393А при отсутствии давления должен иметь сопротивление 310...320 Ом, при давлении в 4 кг/см' — 115...130 Ом, при давлении в 6 кг/см' — 55...65 Ом, при давлении в 8 кг/см' — 0...15 Ом. ) в данном случае, тут стоит только программно откорректировать, отображение точки во втором разряде индикатора.
Операционный усилитель , хоть и является небольшим усложнением схемы, зато с его помощью можно добиться лабораторной точности показаний,  даже с таким примитивным датчиком давления как ММ393А ( это самый доступный, другие специализирование стоят достойных денег  ).
А выход из МК, настраиваемого порога включения/выключения с настраиваемым гистерезисом (или просто сигнал) дополнительного устройства, делает эту схему полноценной, для любого применения !!!!
А дальше, ведь можно сделать ещё интереснее 2 в 1. Например: манометр/манометр , манометр/сумеречный переключатель ……… , ну в общем по этому же принципу схемы сумеречного переключателя какие угодно комбинации устройств.
Не знаю, будет ли Вам  интересно модифицировать данную прошивку, для схемы 2 в 1.??
В любом случае, спасибо Вам , что Вы сделали такую ценную схему для всех радиолюбителей!
Сам я  отношусь к 1% людей которым не по силам программирование.  :) , а также я вхожу ещё в одну категорию любителей, которые любят мастерить  такие небольшие устройства  «электронные помощники»  в повседневной жизни……
Фото внешнего вида  датчика давления .
http://c2.at.ua/l/9/datchik_mm393a.jpg
Схема
http://c2.at.ua/3m/L/S_avt/3-1-f.jpg
Архив файлов с моделью схемы в протеусе
(сразу не нашел этот форум, извиняйте , это сообщение продублировано на форуме http://bascom.at.ua ),

+2

4

Тексь не досмотрел ....... Данная программа для сумеречного выключателя работает так 0V=0%   5V=100% , а для манометра требуется чтобы показания были 0V=100%   5V=10% , значит тут только корректировкой точки не обойтись , может и можно аналоговым способом инвертировать , но  что то пока не пришла идея как инвертировать с такой же линейностью......

0

5

С кодом помочь готов, без проблем. Однако сейчас в железе проверить нет возможности (операционник + датчик). Толкового описания характеристик не нашел. Требуется таблица, зависимость сопротивления(напряжения) от давления. Далее, описать подробнее режимы работы прибора. Данная прошивка занимает 33% памяти МК, так что много чего можно добавить.
А про универсальность, промышленные варианты данного устройства одинакого работают как с фоторезистором (фотореле), так и с терморезистором (термостат), МК по большому счету все равно, какой датчик подключен. На МК достаточно свободных ног выводов АЦП, к которым можно подключить различные датчики одновременно. Поэтому прошу составить требуемый алгоритм работы устройства и необходимые требования, а дальше дело техники. Ваша схема, моя прошивка. Результаты, как обычно, оставлять здесь.  :writing:

0

6

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

Требуется таблица, зависимость сопротивления(напряжения) от давления.

Датчик давления ММ393А изменяет  своё сопротивление так: при отсутствии давления  сопротивление 310...320 Ом, при давлении в 4 кг/см' — 115...130 Ом, при давлении в 6 кг/см' — 55...65 Ом, при давлении в 8 кг/см' — 0...15 Ом. Применив операционый усилитель (стандартная схема подключения ОУ  в амперметрах) его очень легко будет подстроить при существуещем измерении МК , но....

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

программа для сумеречного выключателя работает так 0V=0%   5V=100% , а для манометра требуется чтобы показания были 0V=100%   5V=10% ......

вот здесь еще нужно разобратся, в протеусе подключение датчика сделано как нужно, там в общем то и видно что показания для манометра  идут наоборот.

0

7

Что касается реализовать 2 в 1,  так алгоритм существующей программы таков, что он уже, вроде как, на все случаи жизни....  :)  остаётся сделать одновременный вывод информации на два трехразрядных семисигментных индикатора и  возможность подключать различные датчики одновременно , а также для каждого "канала" индувидуальная настройка  меню.

0

8

Бррр  :canthearyou: все в кучу и ничего конкретного.

Чтобы составить формулу расчета давления от напряжения на входе канала АЦП, нужна таблица(несколько соседних начений и   рабочий диапазон).

     

остаётся сделать одновременный вывод информации на два трехразрядных семисигментных индикатора

Не проблема. Выводы (A..H) 2го индикатора цепляем на соответствующие выводы 1го индикатора, общие выводы (1..3) 2го индикатора на свободные пины порта B.
       

возможность подключать различные датчики одновременно

Подключать различные датчики на один и тот же вход АЦП МК можно только при условии их одинаковых характеристик, либо указать прибору, какой именно датчик подключен на конкретный вход АЦП, иначе показания будут бессмысленными.
       

а также для каждого "канала" индувидуальная настройка  меню

А здесь возникает вопрос, по какому приоритету уставок разных датчиков будет срабатывать нагрузка(AND, OR) ?

Да и вообще, честно говоря, пока трудно представляю назначение прибора. Где требуется одновременно контролировать давление и уровень освещенности, и что является нагрузкой?  :dontknow:

Отредактировано MACTEPok (2011-06-15 23:09:15)

0

9

В данном случае составлять формулу расчета давления от напряжения не имеет смысла, так как датчик ММ393А хоть я и считаю что очень доступен, но он не панацея , так как завтра появится другой любитель у которого найдется другой датчик ( например из этих же простых ;
Датчик ММ358 при отсутствии давления  имеет сопротивление 160...175 Ом, при давлении в 2 кг/см' — 110...114 Ом, при давлении в 4 кг/см' — 58...65 Ом, при давлении в 6кг/см' — 0...5 Ом
Датчик 23.3839 при отсутствии давления имеет сопротивление 305...330 Ом, при давлении в 1,5 кг/см' — 180...200 Ом, при давлении в 4,5 кг/см' — 70...80 Ом, при давлении в 6кг/см' — 0...8 Ом)

Я думаю, что все эти датчики можно заставить корректно работать с помощью некоторой аналоговой обвязки...
В существующей схеме на вход  АЦП МК приходит от 0 до 5 вольт, что отображается на индикаторе в цифрах от 0 до 100, такой же способ работы  АЦП подойдет и для давления , температуры и освещения (везде ориентируемся на резисторный датчик) даже  таким же способом из существующей схемы с прошивкой, можно сделать вольтметр или амперметр, добавив на входе делитель или еще какую аналоговую обвязку ( решение останется только куда двигать точку в амперметре 100А или 10,0А или 1,00А так же и вольтметр 100 V) ..... в общем опять много пишу ....   
Измерительный вход надо оставлять как есть, ориентированные на резисторные датчики.
Назначение, я тоже не представляю пока где потребуется давление и уровень освещенности , но если будет там использоваться возможность задаваемого порога срабатывания, то  я не стану утверждать что такой прибор не найдет применения в  какой либо автоматизации .
А реальней применение это давление - давление , давление - температура, температура - температура , температура - освещение, давление - вольтметр... ну в общем может я как то и немного непонятно излагаю и список комбинаций, прикидываю он должен быть 4х4... И везде фишка у этого прибора задаваемый порог срабатывания с гистерезисом, а вот вопрос какой (AND, OR) у меня пока запроса никакого нет...
В этом направлении  наверное пока, оставить как есть.
Просто сделать два одинаковых канала по уже готовому алгоритму работы.
Относительно давления , то здесь очевидно нужно сделать инвертирование , чтобы при подаче на вход МК 0 вольт показания 10,0, при подаче 5 вольт показания 0,0.
Я сейчас по поводу линейного инвертирования , занимаюсь самообразованием, придумываю варианты как это сделать, просто аналоговой частью..:) если будет найдено решение, то останется только один вариант модернизации, сделать два одинаковых канала по уже готовому алгоритму работы.

Кстати , а что это там в статье на сайте в архиве на схеме пины (выводы (A..H)) указаны одни, а прошивка выложена под другие, я не знаю как бы я разобрался, если б не протеус ........ тут на форуме правильно, а там любой запутается :)

Отредактировано Coviraylhik (2011-06-16 01:25:41)

0

10

решение останется только куда двигать точку в амперметре 100А или 10,0А или 1,00А так же и вольтметр 100 V

До кучи подключить дополнительную кнопку, которой переключать входы АЦП и кнопками UP, DOWN переключать разрядность (двигать точку), инвертирование. Это при двух каналах АЦП.
       

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

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

при подаче на вход МК 0 вольт показания 10,0

Чтобы не мудрить, изменения сделать в делителе напряжения (Датчик выдает 0 значение, а на вход МК подается напряжение, соответствующее 10%, постоянную составляющую ввести, думаю, роли не сыграет)
         

Кстати , а что это там в статье на сайте в архиве на схеме пины (выводы (A..H)) указаны одни, а прошивка выложена под другие

Косяк мой. На форуме прошивку выложил под указанную схему. А на сайте под готовую плату, но и рисунок схемы я тоже изменил!
         

а вот вопрос какой (AND, OR) у меня пока запроса никакого нет...

Допустим подключены 2 датчика температуры. t_on1=5C, t_off1=10C; t_on2=7C, t_off2=15C. Как думаете, каким образом будет вести себя нагрузка?

0

11

Тут мы подразумеваем, что два датчика подключены на два разных входа ( РС5 и допустим РС4)?
Так я здесь попробовал нарисовал графики, по такому принципу как работает сейчас, режим вкл/выкл нормально должен управлять нагрузкой.

http://c2.at.ua/3m/L/S_avt/gistM.gif

0

12

:unsure: угу. Раз нагрузки сидят на портах PB3 и PB4, а на графиках по одному параметру, значит вы хотите получить 2 независимых канала в одном приборе?  :tired: Похоже не о том я думал: я имел ввиду, когда нагрузка управляется по контролю 2х величин (например, днем управление по температуре), а на деле вам нужно управлять 2мя нагрузками от соответствующего датчика. Мда

0

13

Да  именно я про два одинаковых канала  по существующей схеме, но входа но только считывание информации проинвертировать, чтобы датчики сидели одним концом на земле оссобено давление без этого никак, ну освещение и температура тоже будут по такому подключению. В протеусе посмотрел, будут аналогично работать , да и проще когда к общей шине.
http://c2.at.ua/3m/L/S_avt/9/BT.gif

...........я имел ввиду, когда нагрузка управляется по контролю 2х величин (например, днем управление по температуре), а на деле вам нужно управлять 2мя нагрузками...........

По этому поводу, с пол слова чесно говоря пока не понял :)

Отредактировано Coviraylhik (2011-06-16 19:02:03)

0

14

Задачу понял. на днях выложу вариант кода.

А про контроль 2х величин и приоритет. Столкнулся с этим вопросом в устройстве акваконтроллера Акваконтроллер. Есть функция таймера и термостата. Хотел заставить работать термостат в определенный период времени (приоритет на таймер). Так как этот самый приоритет выбрать там нельзя было, устройство работало как обычный термостат в любой промежуток времени. Т.е. нагрузка могла управляться либо термостатом либо таймером.  :dontknow: (это в старой версии прошивки. новую не испытывал).

0

15

Сила этот акваконтроллер только когда аквариума нет то и интереса нет, к такому устройству (да и схема там сложновата)

Так-сь по делу, если будет время на модификацию сумеречного выключателя , так жду с нетерпением, уже есть у меня прогресс получилось комплимировать из кода нех,    и   ......   усе , остальные мои редакции кода приносят только вред прошивке :blush:
Вижу там в коде строчку  "чтобы показания не скакали" очень важно при таких движущихся датчиках, чтобы они действительно не скакали, ну может там обновления экрана раз в 0.5 сек что-ли.
И чтобы кнопки без дребезга  .......
А вообще я тут конечно дилетант извиняйте что не так....

0

16

2х канальное фотореле, термостат и тд. на резистивных датчиках.
2 независимые канала АЦП, управляющие соответствующим каналом нагрузки.
      По замечаниям:
* показания обоих каналов изменяются от 0 до 100 при напряжении на входах АЦП от 5 до 0 В
* 2 светодиодных дисплея, каждый отвечает за свой канал
* сопротивления R2, R3 выбираются исходя из сопротивления датчиков. Для необходимого диапазона значений расчитывается делитель напряжения
* для удобства настройки на каждом индикаторе отображаются уставки только своего канала, причем, второй индикатор продолжает показывать измеряемую величину
* также при неверном вводе уставок, появляется сообщение ошибки на дисплее соответствующего канала
* осуществлен автоматический выход из меню через ~5 сек.
* автоматическое определение рабочего режима (нагреватель/охладитель)



Код:
'*******************************************************************************
'* Filename    : Сумеречный переключатель на 2 независимых канала              *
'* Revision    : 2.0                                                           *
'* Controller  : ATMEGA8                                                       *
'* Compiler    : BASCOM-AVR 2.0.6.1                                            *
'* Author      : MACTEPOK                                                      *
'*******************************************************************************
$regfile = "m8def.dat"                                      'определяем контроллер
$crystal = 8000000                                          'внутренний генератор
'$sim
$lib "mcsbyte.lbx"                                          'подключаем библиотеку функций

Config Pinc.0 = Input : Portc.0 = 1                         'кнопка УСТ
Config Pinc.1 = Input : Portc.1 = 1                         'кнопка Вверх
Config Pinc.2 = Input : Portc.2 = 1                         'кнопка Вниз

Config Portd = Output : Config Portb = Output               'порты на выход к которым подключен индикатор

Load1 Alias Portb.3                                         'нагрузка №1
Load2 Alias Portb.4                                         'нагрузка №2

Config Adc = Single , Prescaler = Auto , Reference = Avcc   'настраиваем АЦП

Dim W As Byte , Y As Byte , X As Byte , I As Byte , Z As Byte , Chislo(6) As Integer , Light As Integer , Light_on As Byte , Light_off As Byte , Pressure As Integer , Pressure_on As Byte , Pressure_off As Byte , Sostoyanie As Byte , Sostoyanie_2 As Byte , Copy_print As Integer , Copy_print_sec As Integer , _print As Integer , _print_sec As Integer , Pokazaniya As Integer , View_menu As Byte , Booton_flag As Bit , Count As Word , Error_flag As Bit
Dim Menu_punkt As Byte                                      'пункт меню
Dim Set_flag As Bit                                         'флаг режима настройки уставок
Dim Podskaz_flag As Bit , Podskaz_flag_sec As Bit           'флаги режима отображения подсказок на соответствующих каналах
Dim Default As Eram Byte At &H14                            'переменная EEPROM для записи начальных уставок для первого включения прибора

A Alias Portd.5 : B Alias Portd.7 : C Alias Portd.3 : D Alias Portd.1       'порты, к которым подключены сегменты индикатора
E Alias Portd.0 : F Alias Portd.6 : G Alias Portd.4 : H Alias Portd.2       '
Dig1 Alias Portb.0 : Dig2 Alias Portb.1 : Dig3 Alias Portb.2       '  порты, к которым подключены общие аноды 1го индикатора
Dig1_sec Alias Portb.5 : Dig2_sec Alias Portb.6 : Dig3_sec Alias Portb.7       '  порты, к которым подключены общие аноды 2го индикатора

For X = 1 To 6                                              ' присваиваем всем цифрам пустоту, чтоб в момент включения не высвечивались нули
Chislo(x) = 11
Next

Config Timer0 = Timer , Prescale = 8 : On Timer0 Pulse      ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer , Prescale = 1 : On Timer1 Bootons    ' конфигурируем таймер 1 и назначаем подпрограмму которая выполняется при переполнении таймера
Enable Interrupts : Enable Timer0 : Enable Timer1           ' разрешаем прерывания, таймер 0,   таймер 1
Start Timer0 : Start Timer1

If Default = 255 Then                                       'при первом запуске, когда Default=255
   Light_off = 50                                           'присваиваем начальный уставки
   Light_on = 40
   Pressure_on = 30
   Pressure_off = 40
   Writeeeprom Light_on , 0                                 ' Записываем в EEPROM уставку ON1
   Writeeeprom Light_off , 5                                ' Записываем в EEPROM уставку OFF1
   Writeeeprom Pressure_on , 10                             ' Записываем в EEPROM уставку ON2
   Writeeeprom Pressure_off , 15                            ' Записываем в EEPROM уставку OFF2
   Default = 100                                            ' присваиваем значение 100(произвольное, отличное от 255) и больше этот кусок кода выполняться не будет
End If
   Readeeprom Light_on , 0                                  ' Считываем из EEPROM уставку ON1
   Readeeprom Light_off , 5                                 ' Считываем из EEPROM уставку OFF1
   Readeeprom Pressure_on , 10                              ' Считываем из EEPROM уставку ON2
   Readeeprom Pressure_off , 15                             ' Считываем из EEPROM уставку OFF2

   Start Adc                                                ' начало преобразования
Do

   If X > 8 Then                                            ' увеличили период опроса АЦП, чтобы значения не прыгали
      Stop Timer0 : Stop Timer1                             ' на время преобразования останавливаем таймеры
      Light = Getadc(5)                                     'опрос фоторезистора (1 канал)
      Light = 1023 - Light
      Light = Light / 10                                    'пересчет
      If Light > 100 Then Light = 100
      Pressure = Getadc(4)                                  'опрос датчика давления (2 канал)
      Pressure = 1023 - Pressure
      Pressure = Pressure / 10
      If Pressure > 100 Then Pressure = 100
   X = 0                                                    '
   End If
   Start Timer0 : Start Timer1
   If Light_on < Light_off Then                             'если уставка ON1 < OFF1 то режим нагревателя
      If Light <= Light_on Then Sostoyanie = 1              'если освещенность ниже уставки ON1, то включаем нагрузку №1
      If Light >= Light_off Then Sostoyanie = 0             'если освещенность выше уставки OFF1, то выключаем нагрузку  №1
   Else                                                     'если уставка ON1 > OFF1 то режим охладителя
      If Light >= Light_on Then Sostoyanie = 1              'если освещенность выше уставки ON1, то включаем нагрузку №1
      If Light <= Light_off Then Sostoyanie = 0             'если освещенность ниже уставки OFF1, то выключаем нагрузку  №1
   End If

   If Sostoyanie = 1 Then Set Load1 Else Reset Load1        'управление 1м каналом нагрузки

   If Pressure_on < Pressure_off Then                       'если уставка ON2 < OFF2 то режим нагревателя
      If Pressure <= Pressure_on Then Sostoyanie_2 = 1      'если давление ниже уставки ON2, то включаем нагрузку  №2
      If Pressure >= Pressure_off Then Sostoyanie_2 = 0     'если давление выше уставки OFF2, то выключаем нагрузку  №2
   Else                                                     'если уставка ON2 > OFF2 то режим охладителя
      If Pressure >= Pressure_on Then Sostoyanie_2 = 1      'если давление выше уставки ON2, то включаем нагрузку  №2
      If Pressure <= Pressure_off Then Sostoyanie_2 = 0     'если давление ниже уставки OFF2, то выключаем нагрузку  №2
   End If

   If Sostoyanie_2 = 1 Then Set Load2 Else Reset Load2      'управление 2м каналом нагрузки

Loop

'*******************************************************************************
' Индикация

Pulse:
   If View_menu <> 0 And Error_flag = 0 Then Incr Count     'если находимся в меню и нет ошибки ввода уставок,то инкриментируем счетчик, который отвечает за автоматический выход из меню (~ через 5 сек)
   If Count > 7000 Then                                     'задается время автоматического выхода из меню
      Count = 0                                             'сброс счетчика
      View_menu = 0                                         ' выход из меню в основной режим
   End If
   H = 1                                                    ' выключаем точку на индикаторе
   Stop Timer0                                              'останавливаем таймер 0
   Select Case View_menu                                    'в зависимости от пункта меню, записываем в переменные расчета следующие данные
      Case 0 :
         _print = Light                                     ' основной режим. 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure                              ' основной режим. 2й индикатор показывает значение АЦП 2го канала
      Case 1 :
         _print = Light_on                                  ' 1й индикатор показывает значение уставки ON1
         _print_sec = Pressure                              ' 2й индикатор показывает значение АЦП 2го канала
      Case 2 :
         _print = Light_off                                 ' 1й индикатор показывает значение уставки OFF1
         _print_sec = Pressure                              ' 2й индикатор показывает значение АЦП 2го канала
      Case 3 :
         _print = Light                                     ' 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure_on                           ' 2й индикатор показывает значение уставки ON2
      Case 4 :
         _print = Light                                     ' 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure_off                          ' 2й индикатор показывает значение уставки OFF2
   End Select

   If Podskaz_flag = 0 Then                                 'если не выводим на 1й индикатор подсказки, то работаем с числами
      Copy_print = _print                                   'скопируем переменную до обработки

         For I = 1 To 3                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print Mod 10                          ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print = _print / 10                               ' отсекаем последнюю цифру от числа _print (123/10=12)
         Next

      If Copy_print < 100 Then Chislo(3) = 11               'если  переменная < 100, то устанавливаем в 3м разряде пустоту
      If Copy_print < 10 Then Chislo(2) = 11                ' если  переменная < 10, то устанавливаем в 2м разряде пустоту
   End If
   If Podskaz_flag_sec = 0 Then                             'если не выводим на 2й индикатор подсказки, то работаем с числами
      Copy_print_sec = _print_sec                           'скопируем переменную до обработки
         For I = 4 To 6                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print_sec Mod 10                      ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print_sec = _print_sec / 10                       ' отсекаем последнюю цифру от числа _print_sec (123/10=12)
         Next
      If Copy_print_sec < 100 Then Chislo(6) = 11           'если  переменная < 100, то устанавливаем в 3м разряде пустоту
      If Copy_print_sec < 10 Then Chislo(5) = 11            ' если  переменная < 10, то устанавливаем в 2м разряде пустоту
   End If

   Reset Dig1 : Reset Dig2 : Reset Dig3 : Reset Dig1_sec : Reset Dig2_sec : Reset Dig3_sec
   Incr W : If W > 6 Then W = 1                             ' выбираем какую цифру сейчас включать
   Y = 0
   Gosub Look : A = Z                                       ' переходим к подпрограмме Look, которая определяет нужно ли сейчас загорется сегменту А
   Gosub Look : B = Z
   Gosub Look : C = Z
   Gosub Look : D = Z
   Gosub Look : E = Z
   Gosub Look : F = Z
   Gosub Look : G = Z

   Select Case W                                            ' включаем цифру(разряд) которую выбрали (w). Подаем плюс на общий провод конкретной цифры (разряда)
      Case 1 :
         Set Dig1
      Case 2 :
         Set Dig2
      Case 3 :
         Set Dig3
      Case 4 :
         Set Dig1_sec
      Case 5 :
         Set Dig2_sec
      Case 6 :
         Set Dig3_sec
   End Select
   Start Timer0
Return
'
Look:                                                       ' подпрограмма которая определяет нужно ли сейчас гореть сегменту, который вызвал эту подпрограмму
   Z = Chislo(w) * 7 : Z = Y + Z                            ' определяем порядковый номер числа из таблици DATA. W - это цифра которую будем выводить 1..2..3, Y это номер сегмента (A=0 B=1 C=2...G=7)
   Z = Lookup(z , Cifri)                                    ' выбираем из таблици включить или выключить нужный сегмент
   Incr Y                                                   'Y это номер сегмента (A=0 B=1 C=2...). Chislo(w) * 7 - переход на начало нужной строки Data.Z = Y + Z - по очереди перебираем сегменты в строке.
Return
'
Cifri:
' таблица сегментом для индикаторов с общим плюсом      |Chislo(i)| Символ |
Data 0 , 0 , 0 , 0 , 0 , 0 , 1                              '0
Data 1 , 0 , 0 , 1 , 1 , 1 , 1                              '1
Data 0 , 0 , 1 , 0 , 0 , 1 , 0                              '2
Data 0 , 0 , 0 , 0 , 1 , 1 , 0                              '3
Data 1 , 0 , 0 , 1 , 1 , 0 , 0                              '4
Data 0 , 1 , 0 , 0 , 1 , 0 , 0                              '5
Data 0 , 1 , 0 , 0 , 0 , 0 , 0                              '6
Data 0 , 0 , 0 , 1 , 1 , 1 , 1                              '7
Data 0 , 0 , 0 , 0 , 0 , 0 , 0                              '8
Data 0 , 0 , 0 , 0 , 1 , 0 , 0                              '9
Data 1 , 1 , 1 , 1 , 1 , 1 , 0                              '10           "-"
Data 1 , 1 , 1 , 1 , 1 , 1 , 1                              '11           ""
Data 1 , 1 , 1 , 0 , 0 , 0 , 1                              '12           "L"
Data 1 , 1 , 0 , 1 , 0 , 1 , 0                              '13           "n"
Data 0 , 1 , 1 , 1 , 0 , 0 , 0                              '14           "F"
Data 0 , 1 , 1 , 0 , 0 , 0 , 0                              '15           "E"
Data 1 , 1 , 1 , 1 , 0 , 1 , 0                              '16           "r"
Data 1 , 1 , 1 , 1 , 0 , 0 , 1                              '17           "I"
Data 0 , 0 , 0 , 1 , 1 , 0 , 0                              '18           "g"

'*******************************************************************************
'
'*******************************************************************************
' Опрос кнопок
Bootons:
   Incr X
   Stop Timer1
      If Pinc.0 = 0 And Booton_flag = 0 Then Gosub Set_mode ' Нажатие кнопки УСТ
      If Set_flag = 1 And Pinc.0 = 1 Then                   'Кнопки Вверх и Вниз активны только после входа в меню
         If Pinc.1 = 0 Then Gosub Up_const
         If Pinc.2 = 0 Then Gosub Down_const
      End If
    If Pinc.0 = 1 And Pinc.1 = 1 And Pinc.2 = 1 Then Reset Booton_flag       'сброс флага удержания кнопки
   Start Timer1 : Start Timer0
Return
'*******************************************************************************
'
'
Set_mode:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Set Set_flag                                             ' поднимаем флаг режима настройки уставок (находимся в меню)
   Set Booton_flag                                          ' поднимаем флаг удержания кнопки (пока не сбросится, в следующий пункт меню не попадаем)
   Count = 0                                                'сброс счетчика автоматического выхода из меню
   If Light_on = Light_off Or Pressure_on = Pressure_off Then Gosub Errors       'Блокировка ввода уставок. Переходим в подпрограмму индикации ошибки
   Incr View_menu                                           ' следующий пункт меню
   If View_menu > 4 Then View_menu = 0                      ' всего 4 пункта меню, 0й - основной режим

      Select Case View_menu                                 'индикация подсказок пунктов меню
       Case 0 :                                             ' ---
           Set Podskaz_flag
           Set Podskaz_flag_sec
           Chislo(1) = 10
           Chislo(2) = 10
           Chislo(3) = 10
           Chislo(4) = 10
           Chislo(5) = 10
           Chislo(6) = 10
           Reset Set_flag                                   '
           Writeeeprom Pressure_off , 15                    ' запись уставки OFF2 в EEPROM
           Waitms 500

       Case 1 :                                             ' On1
           Set Podskaz_flag                                 'Поднимаем флаг вывода подсказок (буквы) на 1й индикатор
           Chislo(1) = 1
           Chislo(2) = 13
           Chislo(3) = 0
           Waitms 500

       Case 2 :                                             ' OF1
           Set Podskaz_flag                                 'Поднимаем флаг вывода подсказок (буквы) на 1й индикатор
           Chislo(1) = 1
           Chislo(2) = 14
           Chislo(3) = 0
           Writeeeprom Light_on , 0                         ' запись уставки ON1 в EEPROM
           Waitms 500

       Case 3 :                                             ' On2
           Set Podskaz_flag_sec                             'Поднимаем флаг вывода подсказок (буквы) на 2й индикатор
           Chislo(4) = 2
           Chislo(5) = 13
           Chislo(6) = 0
           Writeeeprom Light_off , 5                        ' запись уставки OFF1 в EEPROM
           Waitms 500

       Case 4 :                                             ' OFF2
           Set Podskaz_flag_sec                             'Поднимаем флаг вывода подсказок (буквы) на 2й индикатор
           Chislo(4) = 2
           Chislo(5) = 14
           Chislo(6) = 0
           Writeeeprom Pressure_on , 10                     ' запись уставки ON2 в EEPROM
           Waitms 500

           End Select

   Reset Podskaz_flag
   Reset Podskaz_flag_sec
Return
'
Errors:
   Set Error_flag                                           ' поднимаем флаг ошибки
   If Light_on = Light_off Then
      Set Podskaz_flag
      Chislo(1) = 16
      Chislo(2) = 16                                        'Выводим подсказку Err и мигаем на 1м индикаторе
      Chislo(3) = 15
      Waitms 500
      Chislo(1) = 11
      Chislo(2) = 11
      Chislo(3) = 11
      Waitms 500
      Chislo(1) = 16
      Chislo(2) = 16
      Chislo(3) = 15
      Waitms 500
      Chislo(1) = 11
      Chislo(2) = 11
      Chislo(3) = 11
      Waitms 500
   End If
   If Pressure_on = Pressure_off Then
      Set Podskaz_flag_sec
      Chislo(4) = 16
      Chislo(5) = 16                                        'Выводим подсказку Err и мигаем на 2м индикаторе
      Chislo(6) = 15
      Waitms 500
      Chislo(4) = 11
      Chislo(5) = 11
      Chislo(6) = 11
      Waitms 500
      Chislo(4) = 16
      Chislo(5) = 16
      Chislo(6) = 15
      Waitms 500
      Chislo(4) = 11
      Chislo(5) = 11
      Chislo(6) = 11
      Waitms 500
   End If
   Select Case View_menu                                    ' взависимости от того, в каком пункте меню ввели неверное значение
      Case 0 :                                              ' возвращаем из EEPROM предыдущие значения
      Case 1 :
         Readeeprom Light_on , 0
      Case 2 :
         Readeeprom Light_off , 5
      Case 3 :
          Readeeprom Pressure_on , 10
      Case 4 :
         Readeeprom Pressure_off , 15
   End Select
   Decr View_menu                                           ' возвращаемся в предыдущий пункт меню (в ошибочный)
   Count = 0 : Reset Error_flag
Return
'
Up_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Count = 0
   Select Case View_menu
      Case 1 :
            If Light_on < 100 Then Incr Light_on
      Case 2 :
            If Light_off < 100 Then Incr Light_off
      Case 3 :
            If Pressure_on < 100 Then Incr Pressure_on
      Case 4 :
            If Pressure_off < 100 Then Incr Pressure_off
   End Select
   Waitms 40
Return
'
'
Down_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Count = 0
   Select Case View_menu
      Case 1 :
            If Light_on > 0 Then Decr Light_on
      Case 2 :
            If Light_off > 0 Then Decr Light_off
      Case 3 :
            If Pressure_on > 0 Then Decr Pressure_on
      Case 4 :
            If Pressure_off > 0 Then Decr Pressure_off
   End Select
   Waitms 40
Return

увеличить

Отредактировано MACTEPok (2011-06-21 14:14:01)

+1

17

Вау. http://c2.at.ua/sml/smile205.gif   теперь стало в  два раза интереснее.
Пока только опробовал в протеусе, работает устройство 2 в 1.
Входа проинвертиованы датчик давления в правильной последовательности отображает значения.
Я тут еще немного поэксперементировал по такому же включению через ОУ, с NTC термистором вроде тоже должно быть всё ОК , от 0°C до 100°C наблюдаю линейность .
Только один пункт не понял * автоматическое определение рабочего режима (нагреватель/охладитель) что и как определяется автоматически?
Сейчас по принципу работы точка на индикаторе не задействована совсем, MACTEPok выведите её во втором разряде индикаторов , если она не будет нужна просто её можно не подключать  физически Н.
Спасибо MACTEPok вы придумали простую и довольно таки универсальную схемку  :)

0

18

Да, и архив с протеусом

увеличить

Отредактировано Coviraylhik (2011-06-21 17:18:11)

0

19

В режиме термостата:
    при ton<t<toff - режим нагревателя
    при ton>t>toff - режим охладителя

0

20

Дополнение:
       * в основном режиме, при удержании кнопки UP, нажимая на кнопку SET у первого идикатора меняется разряд, в котором будет гореть точка
       * в основном режиме, при удержании кнопки DOWN, нажимая на кнопку SET у второго идикатора меняется разряд, в котором будет гореть точка
        * состояние точки на обоих индикаторах сохраняется в EEPROM

Код:
'*******************************************************************************
'* Filename    : Сумеречный переключатель на 2 независимых канала              *
'* Revision    : 2.0                                                           *
'* Controller  : ATMEGA8                                                       *
'* Compiler    : BASCOM-AVR 2.0.6.1                                            *
'* Author      : MACTEPOK                                                      *
'*******************************************************************************
$regfile = "m8def.dat"                                      'определяем контроллер
$crystal = 8000000                                          'внутренний генератор
'$sim
$lib "mcsbyte.lbx"                                          'подключаем библиотеку функций

Config Pinc.0 = Input : Portc.0 = 1                         'кнопка УСТ
Config Pinc.1 = Input : Portc.1 = 1                         'кнопка Вверх
Config Pinc.2 = Input : Portc.2 = 1                         'кнопка Вниз

Config Portd = Output : Config Portb = Output               'порты на выход к которым подключен индикатор

Load1 Alias Portb.3                                         'нагрузка №1
Load2 Alias Portb.4                                         'нагрузка №2

Config Adc = Single , Prescaler = Auto , Reference = Avcc   'настраиваем АЦП

Dim W As Byte , Y As Byte , X As Byte , I As Byte , Z As Byte , Chislo(6) As Integer , Light As Integer , Light_on As Byte , Light_off As Byte , Pressure As Integer , Pressure_on As Byte , Pressure_off As Byte , Sostoyanie As Byte , Sostoyanie_2 As Byte , Copy_print As Integer , Copy_print_sec As Integer , _print As Integer , _print_sec As Integer , Pokazaniya As Integer , View_menu As Byte , Booton_flag As Bit , Booton_flag_2 As Bit , Count As Word , Error_flag As Bit
Dim Razryad_1 As Byte , Razryad_2 As Byte,
Dim Menu_punkt As Byte                                      'пункт меню
Dim Set_flag As Bit                                         'флаг режима настройки уставок
Dim Podskaz_flag As Bit , Podskaz_flag_sec As Bit           'флаги режима отображения подсказок на соответствующих каналах
Dim Default As Eram Byte At &H14                            'переменная EEPROM для записи начальных уставок для первого включения прибора

A Alias Portd.5 : B Alias Portd.7 : C Alias Portd.3 : D Alias Portd.1       'порты, к которым подключены сегменты индикатора
E Alias Portd.0 : F Alias Portd.6 : G Alias Portd.4 : H Alias Portd.2       '
Dig1 Alias Portb.0 : Dig2 Alias Portb.1 : Dig3 Alias Portb.2       '  порты, к которым подключены общие аноды 1го индикатора
Dig1_sec Alias Portb.5 : Dig2_sec Alias Portb.6 : Dig3_sec Alias Portb.7       '  порты, к которым подключены общие аноды 2го индикатора

For X = 1 To 6                                              ' присваиваем всем цифрам пустоту, чтоб в момент включения не высвечивались нули
Chislo(x) = 11
Next

Config Timer0 = Timer , Prescale = 8 : On Timer0 Pulse      ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer , Prescale = 1 : On Timer1 Bootons    ' конфигурируем таймер 1 и назначаем подпрограмму которая выполняется при переполнении таймера
Enable Interrupts : Enable Timer0 : Enable Timer1           ' разрешаем прерывания, таймер 0,   таймер 1
Start Timer0 : Start Timer1

If Default = 255 Then                                       'при первом запуске, когда Default=255
   Light_off = 50                                           'присваиваем начальный уставки
   Light_on = 40
   Pressure_on = 30
   Pressure_off = 40
   Razryad_1 = &B11101110
   Razryad_2 = &B11101110
   Writeeeprom Light_on , 0                                 ' Записываем в EEPROM уставку ON1
   Writeeeprom Light_off , 5                                ' Записываем в EEPROM уставку OFF1
   Writeeeprom Pressure_on , 10                             ' Записываем в EEPROM уставку ON2
   Writeeeprom Pressure_off , 15                            ' Записываем в EEPROM уставку OFF2
   Writeeeprom Razryad_1 , 16
   Writeeeprom Razryad_2 , 17
   Default = 100                                            ' присваиваем значение 100(произвольное, отличное от 255) и больше этот кусок кода выполняться не будет
End If
   Readeeprom Light_on , 0                                  ' Считываем из EEPROM уставку ON1
   Readeeprom Light_off , 5                                 ' Считываем из EEPROM уставку OFF1
   Readeeprom Pressure_on , 10                              ' Считываем из EEPROM уставку ON2
   Readeeprom Pressure_off , 15                             ' Считываем из EEPROM уставку OFF2
   Readeeprom Razryad_1 , 16
   Readeeprom Razryad_2 , 17

   Start Adc                                                ' начало преобразования

Do

   If X > 8 Then                                            ' увеличили период опроса АЦП, чтобы значения не прыгали
      Stop Timer0 : Stop Timer1                             ' на время преобразования останавливаем таймеры
      Light = Getadc(5)                                     'опрос фоторезистора (1 канал)
      Light = 1023 - Light
      Light = Light / 10                                    'пересчет
      If Light > 100 Then Light = 100
      Pressure = Getadc(4)                                  'опрос датчика давления (2 канал)
      Pressure = 1023 - Pressure
      Pressure = Pressure / 10
      If Pressure > 100 Then Pressure = 100
   X = 0                                                    '
   End If
   Start Timer0 : Start Timer1
   If Light_on < Light_off Then                             'если уставка ON1 < OFF1 то режим нагревателя
      If Light <= Light_on Then Sostoyanie = 1              'если освещенность ниже уставки ON1, то включаем нагрузку №1
      If Light >= Light_off Then Sostoyanie = 0             'если освещенность выше уставки OFF1, то выключаем нагрузку  №1
   Else                                                     'если уставка ON1 > OFF1 то режим охладителя
      If Light >= Light_on Then Sostoyanie = 1              'если освещенность выше уставки ON1, то включаем нагрузку №1
      If Light <= Light_off Then Sostoyanie = 0             'если освещенность ниже уставки OFF1, то выключаем нагрузку  №1
   End If

   If Sostoyanie = 1 Then Set Load1 Else Reset Load1        'управление 1м каналом нагрузки

   If Pressure_on < Pressure_off Then                       'если уставка ON2 < OFF2 то режим нагревателя
      If Pressure <= Pressure_on Then Sostoyanie_2 = 1      'если давление ниже уставки ON2, то включаем нагрузку  №2
      If Pressure >= Pressure_off Then Sostoyanie_2 = 0     'если давление выше уставки OFF2, то выключаем нагрузку  №2
   Else                                                     'если уставка ON2 > OFF2 то режим охладителя
      If Pressure >= Pressure_on Then Sostoyanie_2 = 1      'если давление выше уставки ON2, то включаем нагрузку  №2
      If Pressure <= Pressure_off Then Sostoyanie_2 = 0     'если давление ниже уставки OFF2, то выключаем нагрузку  №2
   End If

   If Sostoyanie_2 = 1 Then Set Load2 Else Reset Load2      'управление 2м каналом нагрузки

Loop

'*******************************************************************************
' Индикация

Pulse:
   If View_menu <> 0 And Error_flag = 0 Then Incr Count     'если находимся в меню и нет ошибки ввода уставок,то инкриментируем счетчик, который отвечает за автоматический выход из меню (~ через 5 сек)
   If Count > 7000 Then                                     'задается время автоматического выхода из меню
      Count = 0                                             'сброс счетчика
      View_menu = 0                                         ' выход из меню в основной режим
   End If
'   H = 1                                                    ' выключаем точку на индикаторе
   Stop Timer0                                              'останавливаем таймер 0
   Select Case View_menu                                    'в зависимости от пункта меню, записываем в переменные расчета следующие данные
      Case 0 :
         _print = Light                                     ' основной режим. 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure                              ' основной режим. 2й индикатор показывает значение АЦП 2го канала
      Case 1 :
         _print = Light_on                                  ' 1й индикатор показывает значение уставки ON1
         _print_sec = Pressure                              ' 2й индикатор показывает значение АЦП 2го канала
      Case 2 :
         _print = Light_off                                 ' 1й индикатор показывает значение уставки OFF1
         _print_sec = Pressure                              ' 2й индикатор показывает значение АЦП 2го канала
      Case 3 :
         _print = Light                                     ' 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure_on                           ' 2й индикатор показывает значение уставки ON2
      Case 4 :
         _print = Light                                     ' 1й индикатор показывает значение АЦП 1го канала
         _print_sec = Pressure_off                          ' 2й индикатор показывает значение уставки OFF2
   End Select

   If Podskaz_flag = 0 Then                                 'если не выводим на 1й индикатор подсказки, то работаем с числами
      Copy_print = _print                                   'скопируем переменную до обработки

         For I = 1 To 3                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print Mod 10                          ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print = _print / 10                               ' отсекаем последнюю цифру от числа _print (123/10=12)
         Next

      If Copy_print < 100 Then Chislo(3) = 11               'если  переменная < 100, то устанавливаем в 3м разряде пустоту
      If Copy_print < 10 Then Chislo(2) = 11                ' если  переменная < 10, то устанавливаем в 2м разряде пустоту
   End If
   If Podskaz_flag_sec = 0 Then                             'если не выводим на 2й индикатор подсказки, то работаем с числами
      Copy_print_sec = _print_sec                           'скопируем переменную до обработки
         For I = 4 To 6                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print_sec Mod 10                      ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print_sec = _print_sec / 10                       ' отсекаем последнюю цифру от числа _print_sec (123/10=12)
         Next
      If Copy_print_sec < 100 Then Chislo(6) = 11           'если  переменная < 100, то устанавливаем в 3м разряде пустоту
      If Copy_print_sec < 10 Then Chislo(5) = 11            ' если  переменная < 10, то устанавливаем в 2м разряде пустоту
   End If

   Reset Dig1 : Reset Dig2 : Reset Dig3 : Reset Dig1_sec : Reset Dig2_sec : Reset Dig3_sec
   Incr W : If W > 6 Then W = 1                             ' выбираем какую цифру сейчас включать
   Y = 0
   Gosub Look : A = Z                                       ' переходим к подпрограмме Look, которая определяет нужно ли сейчас загорется сегменту А
   Gosub Look : B = Z
   Gosub Look : C = Z
   Gosub Look : D = Z
   Gosub Look : E = Z
   Gosub Look : F = Z
   Gosub Look : G = Z

   Select Case W                                            ' включаем цифру(разряд) которую выбрали (w). Подаем плюс на общий провод конкретной цифры (разряда)
      Case 1 :
         Set Dig1
         If Podskaz_flag = 0 Then H = Razryad_1.1 Else H = 1
      Case 2 :
         Set Dig2
         If Podskaz_flag = 0 Then H = Razryad_1.2 Else H = 1
      Case 3 :
         Set Dig3
         If Podskaz_flag = 0 Then H = Razryad_1.3 Else H = 1
      Case 4 :
         Set Dig1_sec
         If Podskaz_flag_sec = 0 Then H = Razryad_2.1 Else H = 1
      Case 5 :
         Set Dig2_sec
         If Podskaz_flag_sec = 0 Then H = Razryad_2.2 Else H = 1
      Case 6 :
         Set Dig3_sec
         If Podskaz_flag_sec = 0 Then H = Razryad_2.3 Else H = 1
   End Select
   Start Timer0
Return
'
Look:                                                       ' подпрограмма которая определяет нужно ли сейчас гореть сегменту, который вызвал эту подпрограмму
   Z = Chislo(w) * 7 : Z = Y + Z                            ' определяем порядковый номер числа из таблици DATA. W - это цифра которую будем выводить 1..2..3, Y это номер сегмента (A=0 B=1 C=2...G=7)
   Z = Lookup(z , Cifri)                                    ' выбираем из таблици включить или выключить нужный сегмент
   Incr Y                                                   'Y это номер сегмента (A=0 B=1 C=2...). Chislo(w) * 7 - переход на начало нужной строки Data.Z = Y + Z - по очереди перебираем сегменты в строке.
Return
'
Cifri:
' таблица сегментом для индикаторов с общим плюсом      |Chislo(i)| Символ |
Data 0 , 0 , 0 , 0 , 0 , 0 , 1                              '0
Data 1 , 0 , 0 , 1 , 1 , 1 , 1                              '1
Data 0 , 0 , 1 , 0 , 0 , 1 , 0                              '2
Data 0 , 0 , 0 , 0 , 1 , 1 , 0                              '3
Data 1 , 0 , 0 , 1 , 1 , 0 , 0                              '4
Data 0 , 1 , 0 , 0 , 1 , 0 , 0                              '5
Data 0 , 1 , 0 , 0 , 0 , 0 , 0                              '6
Data 0 , 0 , 0 , 1 , 1 , 1 , 1                              '7
Data 0 , 0 , 0 , 0 , 0 , 0 , 0                              '8
Data 0 , 0 , 0 , 0 , 1 , 0 , 0                              '9
Data 1 , 1 , 1 , 1 , 1 , 1 , 0                              '10           "-"
Data 1 , 1 , 1 , 1 , 1 , 1 , 1                              '11           ""
Data 1 , 1 , 1 , 0 , 0 , 0 , 1                              '12           "L"
Data 1 , 1 , 0 , 1 , 0 , 1 , 0                              '13           "n"
Data 0 , 1 , 1 , 1 , 0 , 0 , 0                              '14           "F"
Data 0 , 1 , 1 , 0 , 0 , 0 , 0                              '15           "E"
Data 1 , 1 , 1 , 1 , 0 , 1 , 0                              '16           "r"
Data 1 , 1 , 1 , 1 , 0 , 0 , 1                              '17           "I"
Data 0 , 0 , 0 , 1 , 1 , 0 , 0                              '18           "g"

'*******************************************************************************
'
'*******************************************************************************
' Опрос кнопок
Bootons:
   Incr X
   Stop Timer1
      If Pinc.0 = 0 And Booton_flag = 0 And Pinc.1 = 1 And Pinc.2 = 1 Then Gosub Set_mode       ' Нажатие кнопки УСТ
      If Set_flag = 1 And Pinc.0 = 1 Then                   'Кнопки Вверх и Вниз активны только после входа в меню
         If Pinc.1 = 0 Then Gosub Up_const
         If Pinc.2 = 0 Then Gosub Down_const
      End If
      If Pinc.0 = 0 And Pinc.1 = 0 And View_menu = 0 and Booton_flag_2 = 0 Then Gosub Set_h_led1
      If Pinc.0 = 0 And Pinc.2 = 0 And View_menu = 0 and Booton_flag_2 = 0 Then Gosub Set_h_led2

      If Pinc.0 = 1 And Pinc.1 = 1 And Pinc.2 = 1 Then Reset Booton_flag       'сброс флага удержания кнопки
      If Pinc.0 = 1 Then Reset Booton_flag_2
   Start Timer1 : Start Timer0
Return
'*******************************************************************************
'
'
Set_mode:
   Enable Interrupts : Enable Timer0 : Start Timer0

   Set Set_flag                                             ' поднимаем флаг режима настройки уставок (находимся в меню)
   Set Booton_flag                                          ' поднимаем флаг удержания кнопки (пока не сбросится, в следующий пункт меню не попадаем)
   Count = 0                                                'сброс счетчика автоматического выхода из меню
   If Light_on = Light_off Or Pressure_on = Pressure_off Then Gosub Errors       'Блокировка ввода уставок. Переходим в подпрограмму индикации ошибки
   Incr View_menu                                           ' следующий пункт меню
   If View_menu > 4 Then View_menu = 0                      ' всего 4 пункта меню, 0й - основной режим

      Select Case View_menu                                 'индикация подсказок пунктов меню
       Case 0 :                                             ' ---
           Set Podskaz_flag
           Set Podskaz_flag_sec
           Chislo(1) = 10
           Chislo(2) = 10
           Chislo(3) = 10
           Chislo(4) = 10
           Chislo(5) = 10
           Chislo(6) = 10
           Reset Set_flag                                   '
           Writeeeprom Pressure_off , 15                    ' запись уставки OFF2 в EEPROM
           Waitms 500

       Case 1 :                                             ' On1
           Set Podskaz_flag                                 'Поднимаем флаг вывода подсказок (буквы) на 1й индикатор
           Chislo(1) = 1
           Chislo(2) = 13
           Chislo(3) = 0
           Waitms 500

       Case 2 :                                             ' OF1
           Set Podskaz_flag                                 'Поднимаем флаг вывода подсказок (буквы) на 1й индикатор
           Chislo(1) = 1
           Chislo(2) = 14
           Chislo(3) = 0
           Writeeeprom Light_on , 0                         ' запись уставки ON1 в EEPROM
           Waitms 500

       Case 3 :                                             ' On2
           Set Podskaz_flag_sec                             'Поднимаем флаг вывода подсказок (буквы) на 2й индикатор
           Chislo(4) = 2
           Chislo(5) = 13
           Chislo(6) = 0
           Writeeeprom Light_off , 5                        ' запись уставки OFF1 в EEPROM
           Waitms 500

       Case 4 :                                             ' OFF2
           Set Podskaz_flag_sec                             'Поднимаем флаг вывода подсказок (буквы) на 2й индикатор
           Chislo(4) = 2
           Chislo(5) = 14
           Chislo(6) = 0
           Writeeeprom Pressure_on , 10                     ' запись уставки ON2 в EEPROM
           Waitms 500

           End Select

   Reset Podskaz_flag
   Reset Podskaz_flag_sec
Return
'
Errors:
   Set Error_flag                                           ' поднимаем флаг ошибки
   If Light_on = Light_off Then
      Set Podskaz_flag
      Chislo(1) = 16
      Chislo(2) = 16                                        'Выводим подсказку Err и мигаем на 1м индикаторе
      Chislo(3) = 15
      Waitms 500
      Chislo(1) = 11
      Chislo(2) = 11
      Chislo(3) = 11
      Waitms 500
      Chislo(1) = 16
      Chislo(2) = 16
      Chislo(3) = 15
      Waitms 500
      Chislo(1) = 11
      Chislo(2) = 11
      Chislo(3) = 11
      Waitms 500
   End If
   If Pressure_on = Pressure_off Then
      Set Podskaz_flag_sec
      Chislo(4) = 16
      Chislo(5) = 16                                        'Выводим подсказку Err и мигаем на 2м индикаторе
      Chislo(6) = 15
      Waitms 500
      Chislo(4) = 11
      Chislo(5) = 11
      Chislo(6) = 11
      Waitms 500
      Chislo(4) = 16
      Chislo(5) = 16
      Chislo(6) = 15
      Waitms 500
      Chislo(4) = 11
      Chislo(5) = 11
      Chislo(6) = 11
      Waitms 500
   End If
   Select Case View_menu                                    ' взависимости от того, в каком пункте меню ввели неверное значение
      Case 0 :                                              ' возвращаем из EEPROM предыдущие значения
      Case 1 :
         Readeeprom Light_on , 0
      Case 2 :
         Readeeprom Light_off , 5
      Case 3 :
          Readeeprom Pressure_on , 10
      Case 4 :
         Readeeprom Pressure_off , 15
   End Select
   Decr View_menu                                           ' возвращаемся в предыдущий пункт меню (в ошибочный)
   Count = 0 : Reset Error_flag
Return
'
Up_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Count = 0
   Select Case View_menu
      Case 1 :
            If Light_on < 100 Then Incr Light_on
      Case 2 :
            If Light_off < 100 Then Incr Light_off
      Case 3 :
            If Pressure_on < 100 Then Incr Pressure_on
      Case 4 :
            If Pressure_off < 100 Then Incr Pressure_off
   End Select
   Waitms 30
Return
'
'
Down_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Count = 0
   Select Case View_menu
      Case 1 :
            If Light_on > 0 Then Decr Light_on
      Case 2 :
            If Light_off > 0 Then Decr Light_off
      Case 3 :
            If Pressure_on > 0 Then Decr Pressure_on
      Case 4 :
            If Pressure_off > 0 Then Decr Pressure_off
   End Select
   Waitms 30
Return
'
'
Set_h_led1:
   Set Booton_flag_2
   Rotate Razryad_1 , Left
   Writeeeprom Razryad_1 , 16
Return
'
'
Set_h_led2:
   Set Booton_flag_2
   Rotate Razryad_2 , Left
   Writeeeprom Razryad_2 , 17
Return
'

Отредактировано Александр Д. (2011-06-22 15:05:16)

+1

21

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

http://mkmagazin.almanacwhf.ru/mk_other … timetr.htm     - Смотреть VT1
http://nauchebe.net/2010/05/generatory- … nzistorax/  А тут статья с пояснениями
http://zpostbox.chat.ru/p1.htm - рекомендую схему 16

Отредактировано Skull (2011-06-23 01:31:41)

+1

22

Спасибо!  :cool:

0

23

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

В режиме термостата:    при ton<t<toff - режим нагревателя    при ton>t>toff - режим охладителя

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

Код:
Light = Light / 10                                    'пересчет

Сейчас отображается значение "шкалы"100 <----->0
если изменить      Light = Light / 12    для манометра будет то  что надо "шкалы" 80 <----->0

С точкой пока не получилось у меня, в основном режиме,  удерживаю кнопку ^ +  или другую - , потом нажимаю на кнопку Выбор, изменений у меня нет.

Еще такой вопрос, пробую делать измерение температуры на NTC термисторе 640-10K , возможно здесь интереснее был бы диапазон показаний 999<-----0
Показания то в принципе вроде можно изменить   Light = Light / 1  а вот уставку мне совсем не понятно как сделать 999 .

0

24

Код:
Light = Getadc(5)                                     'опрос АЦП (диапазон от 0 до 1023)
Light = 1023 - Light                                  'инвертирование
Light = Light / 10                                     'тут любая формула для требуемого диапазона или необходимой характеристики
If Light > 100 Then Light = 100                 'верхний предел показаний (если Light > 100, то присваиваем Light = 100)

Coviraylhik
      С точкой пока не получилось у меня, в основном режиме,  удерживаю кнопку ^ +  или другую - , потом нажимаю на кнопку Выбор, изменений у меня нет.

Я проверял на железе, а вы?

По поводу рабочего диапазона показаний от 0 до 999. Для термистора это нормально, но для других датчиковдиапазон от 0 до 100 будет несколько некорректен, так как будет составлять всего 10% от общего диапазона  :dontknow:  Действительно ли это необходимо?

0

25

MACTEPok написал(а):
Coviraylhik  написал(а):

С точкой пока не получилось у меня, в основном режиме,  удерживаю кнопку ^ +  или другую - , потом нажимаю на кнопку Выбор, изменений у меня нет.

Я проверял на железе, а вы?

Я пока в протеусе моделирую , пробую разные варианты подключения датчиков, ваша схема и прошивка очень универсальна, варианты разные только применяй :) :) можно сказать что я прямо увлёкся этим девайсом.:)
Насчет точки, я тут пол дня нажимал кнопки разными вариантами , ..... не вытерпел , написал....... , а точки то, оказываются РАБОТАЮТ это когда в протеус обновляеш версии прошивок работающими с EEPROM , нужно делать переодически сброс постоянных модели (ну в общем фото приложил)

Дальше, выставляю значения так

Код:
   Pressure = Getadc(4)                                  'опрос датчика давления (2 канал)
      Pressure = 1023 - Pressure
      Pressure = Pressure / 1
      If Pressure > 999 Then Pressure = 999

Получается диапазон показаний 100%  от 999 до 0. Но диапазон уставки то остался от 0 до 100 вот это меня интересует , чтобы он тоже был от 0 до 999

увеличить

0

26

Часто  в интернете упоминанается что 1n4148 тоже можно использовать в качестве датчика, с одной стороны он не так прост, есть варианты схем на ОУ линейность вытягивается подстроечниками, есть подключение прямо на ноги МК тогда коэфициент программно ,практических схем  на ОУ маловато пока больше все в теории,
Прямо на ноги МК? Может поделится кто опытом, применения 1n4148 в качестве датчика температуры?
Делаю набросок платы для двух индикаторов, проводников куча..... Попробовал переназначить порты в прошивке получается и даже очень просто :) скажите вот такое переназначение равноценно?
было   E Alias Portd.0 : F Alias Portd.6 :
     Dig1 Alias Portb.0 : Dig2 Alias Portb.1

А вот так например переназначаю,
          Dig1 Alias Portd.0 :  Dig2 Alias Portd.6 :
               E  Alias Portb.0 : F Alias Portb.1

??

увеличить

0

27

Да не так уж много и пишут, на тех же форумах больше вопросов для чего это надо? есть же термопары или настолько важна ценовая разница?
по мне проще купить за 60 руб DS 18B20

0

28

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

было   E Alias Portd.0 : F Alias Portd.6 :     
Dig1 Alias Portb.0 : Dig2 Alias Portb.1
А вот так например переназначаю,         
Dig1 Alias Portd.0 :  Dig2 Alias Portd.6 :               
E  Alias Portb.0 : F Alias Portb.1

Да.

0

29

в качестве термодатчика можно много чего приспособить, главное подать на датчик стабильный ток. Самый простой вариант и распространённый- источник тока на полевом транзисторе.
В качестве датчика можно поставить например высокоомное реле(РЭС-10) или низковольтную лампу накаливания( без стекла ес-но) В "Радио" как-то описывалось.  Измения практически линейны, что позволяет ввести формулу пересчёта, а не строить таблицы.

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

для чего это надо?

Видел, на известных форумах, для защиты БП от перегрева, на радиатор DS-ку вешали. Вот-это,  по моему, извращение, когда там одного диода хватило-бы!

+1

30

kip : Видел, на известных форумах, для защиты БП от перегрева, на радиатор DS-ку вешали. Вот-это,  по моему, извращение, когда там одного диода хватило-бы!

:cool: Поддерживаю

Отредактировано MACTEPok (2011-06-25 12:04:28)

0


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Фотореле. Сумеречный выключатель