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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Управление аквариумом на atmega8 , помогите с оптимизацией кода


Управление аквариумом на atmega8 , помогите с оптимизацией кода

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

1

доброго времени суток, 
говорю сразу, это мой первый проект в bascom и вообще с контроллерами, до этого программы писал давно на бейсике... еще на zx-spectrum  :playful:
написал програмку для моего AQWACOMPа
в протеусе работает,

в данной версии
работаем с 2 датчиками температуры ds18b20  ( код взял у товарища sasha_1973 с темы Исследование работы 8 датчиков Ds18b20, поиск ID, запись в EEPROM MK   но добавил туда возможность поиска нового датчика  и записи его EEPROM  в случае  его замены) 
работа с софтовыми часами  на которых организована реле времени управления основным светом и светодиодной подсветкой в аквариуме
и меню

принцип работы устройства:
при первом  включении - идет поиск датчиков температуры ds18b20 и занесения их  адресов EEPROM
далее устанавливает время в 10:00
устанавливаем время включения Light_satr  основного света и длину светового дня  ( через сколько часов отключится свет после его включения)
далее
устройство на экране отображает  текущее время, состояние включен ли всвет, разрешена ли светодиодная подсветка, температуру в каждом из 2х аквариумов и состояние работы вентиляторов охлаждения
в случае если разрешена в меню светодиодная подсветка ( имитация рассвета ) то она включается  при "текущее время= Light_satr-1час" и выключается при текущее время= Light_satr"  затем включается основное освещение на  "Light_counh =8.9.10.11.12" часов ( выберается в ченю)
после отключения основного света включается светодиодная подсветка  на 1 час ( имитация заката)

далее если температура в первом аквариуме >=28 градусов то включаем один вентилятор охлаждения , если температура в первом аквариуме >=30 градусов то включаем 2 вентилятора
если температура во втором аквариуме >=28 градусов то включаем вентилятор охлаждения ( он там всего один) 

основное меню : 
установка часов
выбор светового дня  ->  подменю: выбор времени включения света, выбор длинны светового дня и запрет\разрешение LED подсветки
термореле ->  подменю: запрет\разрешение включения вентиляторов

но проблема в том что я использовал все 8к FlashROM и мне не хватает  хоть  пару сотен байт для  организации ШИМа  для управления светодиодной подсветкой в аквариуме ( хочу имитировать рассвет, закат и луну)
вот я и порошу гуру программирования помочь оптимизировать код  чтоб хватило еще и на ШИМ для  LED подсветки

алгоритм рассвета : медленное включение втечении 15 минут голубого и белого , затеи гашение в течении 15 минут голубого  и через 45 мин резкое гашение белого
алгоритм заката : резкое включение белого  медленное включение в течении 15 минут красного , затеи гашение в течении 15 минут красного  и белого

http://coal.dp.ua/files/09.png
схема в протеусе примитив, лишь бы проверить работу проги

http://coal.dp.ua/files/atmega8.rar- тут веси проект

исходник

исходник
Код:
'*******************************************************************************
'**********                                                           **********
'**********              КОМПЬЮТЕР ДЛЯ ДВУХ АКВАРИУМОВ                **********
'**********                  автор сего безобразия                    **********
'**********               © Анисимов Сергей   14.08.2013              **********
'**********                                                           **********
'*******************************************************************************
$regfile = "m8def.dat"

$crystal = 8000000
  $hwstack = 40
  $swstack = 16
  $framesize = 32

Config 1wire = Portc.1 : Ds18b20 Alias Pinc.1

 '------------------- Конфигурация LCD ----------------------

Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.0 , Db7 = Portb.1 , E = Portb.3 , Rs = Portb.2
Config Lcd = 20 * 4
Cursor Off Noblink


'------------------- Конфигурация выхода для светодиодика ----------------------
'-------------------------------------------------------------------------------
Config Portc.2 = Output : Culler1 Alias Portc.2 : Reset Portc.2
Config Portc.3 = Output : Culler2 Alias Portc.3 : Reset Portc.3
Config Portc.4 = Output : Culler3 Alias Portc.4 : Reset Portc.4
Config Portc.0 = Output : Rl_light_led Alias Portc.0 : Reset Portc.0
Config Portc.5 = Output : Rl_light Alias Portc.5 : Reset Portc.5
'-------------------------------------------------------------------------------



Dim Id_ds18b20(8) As Byte                                   'Переменная для временного хранения считанного ID Ds18b20
Dim 1_vklyuchenie As Byte
Dim Adres_id_ds18b20 As Word                                'Переменная для хранения адреса считанного ID Ds18b20 в EEPROM контроллера
Dim Kolichestvo_ds18b20 As Word                             'Word/Integer переменная для посчета количества датчиков на линии
Dim Number_saved_ds18b20 As Byte
Dim Temperatura_lcd As String * 8
Dim T As Single , T0 As Single , T1 As Single               'Переменные для преобразования температуры
Dim Byte0 As Byte , Byte1 As Byte , T_celye As Byte , T_desyatye As Byte       'Переменные для преобразования температуры
Dim Zaderzhka_500_ms As Byte                                ', Zaderzhka_100_ms As Byte , Zaderzhka_1000_ms As Word       'Постоянная переменная для хранения значений TIMER0
Dim Znak_temperatura As String * 2 , T_celye_lcd As String * 4 , T_desyatye_lcd As String * 2       'Temperatura As String * 10       'Переменные для преобразования температуры
Dim Temperatura(2) As Byte
Dim Ani_temp(2) As Byte , Aqwanumb As Byte
'-------------------------------------------------------------------------------
Dim 1_id_ds18b20(8) As Byte , 2_id_ds18b20(8) As Byte       'Постоянная переменная для хранения считанного ID Ds18b20
Dim 3_id_ds18b20(8) As Byte , 4_id_ds18b20(8) As Byte       'Постоянная переменная для хранения считанного ID Ds18b20
'-------------------------------------------------------------------------------
Dim A As Byte , B As Byte , C As Byte , D As Byte , E As Byte , X As Byte , Cur_x As Byte       ', Cur_y As Byte       'Постоянная переменная для хранения координат вывода сообщения на LCD

'------------------- Конфигурация выхода для часов ----------------------
' Config Date = Mdy , Separator = /                          ' ANSI-Format
Config Clock = Soft                                         'this is how simple it is
_sec = 0 : _min = 0 : _hour = 0                             ' задаем конкретные значения времени, с которого часы будут начинать считать при включении питания
Config Timer1 = Counter , Edge = Falling , Prescale = 1     ' конфигурируем таймер 1 на подсчет импульсов на кварце, припаянного к Xtal1 Xtal2 на 32768 гц БЕЗ КОНДЕРОВ!
Time$ = "10:20:00"
 '------------------- Конфигурация кнопок ----------------------
Config Portd.2 = Input                                      'Button 1
Button_hour Alias Pind.2
Config Portd.4 = Input                                      'Button 2
Button_min Alias Pind.4
Set Portd.2
Set Portd.4
Dim Bt As Byte , Menu As Byte
Config Portd.3 = Input                                      'Button 3
Button_menu Alias Pind.3
Config Portd.7 = Input : Кнопка Alias Pind.7 : Set Кнопка   'Button 4
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dim Zaderzhka_50_ms As Byte
Dim Edit_menu As Byte , Edit_time As Byte , Linhg_hour_satr As Byte , Linhg_min_satr As Byte , Linhg_time_caunt As Byte , Linhg_led As Byte , Linhg_on As Byte       ', Kyrsor_lcd As String * 1
Dim Return_menu As Byte , Culler_onoff As Byte
Dim Lh As Byte
Dim Err_count As Byte
'-------------------------------------------------------------------------------
'-------------------------- Дополнительные_символы------------------------------
'-------------------------------------------------------------------------------
Deflcdchar 1 , 12 , 18 , 18 , 12 , 32 , 32 , 32 , 32        'значек градуса
Deflcdchar 5 , 14 , 10 , 10 , 10 , 14 , 31 , 31 , 14        'термометр
Deflcdchar 2 , 32 , 2 , 20 , 14 , 5 , 8 , 32 , 32           ' replace [x] with number (0-7)
Deflcdchar 3 , 32 , 8 , 5 , 14 , 20 , 2 , 32 , 32           ' значек вентилятора
Deflcdchar 6 , 10 , 23 , 31 , 31 , 14 , 4 , 14 , 31         ' РЫБА
Deflcdchar 4 , 21 , 32 , 14 , 17 , 21 , 14 , 14 , 14        ' replace [x] with number (0-7)
Deflcdchar 7 , 7 , 14 , 28 , 28 , 28 , 14 , 7 , 32          ' replace [x] with number (0-7)

'*******************************************************************************
'************************     Объявляем подпограммы     ************************
'*******************************************************************************
'-------------------------------------------------------------------------------
' Declare Sub Clear_cursor(byval Cur_x As Byte)
'  Declare Sub Set_cursor(byval Cur_x As Byte)

Declare Sub Sub_edit_led()
Declare Sub Sub_edit_time()
Declare Sub Sub_edit_temp()
Declare Sub Flash_light()
Declare Sub Allarm_temperatura()
Declare Sub Displey_lcd()
Declare Sub Temperature()
Declare Sub Error_ds18b20()
Declare Sub Opros_id_ds18b20()
Declare Sub Poisk_id_ds18b20()
Declare Sub Init_temperatura()
Declare Sub Sensor_not_found()
Declare Sub Pervoe_vklyuchenie()
Declare Sub Identifikacia_ds18b20()
Declare Sub Save_eeprom_id_ds18b20()
Declare Sub Reading_eeprom_id_ds18b20()
Declare Sub Zapros_izmereniya_ds18b20()
Declare Sub Preobrazovanie_temperature()
Declare Function Zapros_kolichestva_ds18b20() As Integer    'Функция запроса количества датчиков Ds18b20 на линии
'-------------------------------------------------------------------------------
'*******************************************************************************
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'------------ Предварительный поиск и программирование ПЗУ Ds18b20 -------------
'-------------------------------------------------------------------------------


Ani_temp(1) = 1
Linhg_time_caunt = 8
Linhg_hour_satr = 8
Culler_onoff = 255
Cls
Lowerline : Lcd "   START  AQWACOMP"
Thirdline : Lcd "         V1.0"
Waitms 3000
Cls
Readeeprom 1_vklyuchenie , 1
If 1_vklyuchenie <> 50 Then Rcall Pervoe_vklyuchenie
Readeeprom Number_saved_ds18b20 , 5
Kolichestvo_ds18b20 = Number_saved_ds18b20
rcall Reading_eeprom_id_ds18b20
rcall Init_temperatura
'










'*******************************************************************************
'*******************ТЕЛО ПРОГРАММЫ********************************

  Enable Interrupts                                         'разрешаем прерывания
 'Enable Timer0
' Config Debounce = 300                                      'разрешаем таймер0
 'Menu = 0
 ' Zaderzhka_50_ms = 0

  Do
'  If Menu > 0 Then
'         If _sec = 0 Then
'          Waitms 1000
'         Incr Return_menu
'           End If
'        If Return_menu >= 5 Then
'        Menu = 0
'        Cls
'        End If
'  End If

      Select Case Menu
      Case 0

         Edit_menu = 0
         Return_menu = 0
         Edit_time = 0
         Zaderzhka_50_ms = 0
         If Zaderzhka_500_ms > 10 Or Zaderzhka_500_ms = 0 Then Rcall Zapros_izmereniya_ds18b20
         Upperline : Lcd Time$                              'Locate 3 , 1
         If Linhg_on = 1 Then
         Lcd "  cіeї іє»"                                   ' свет вкл
         Else
         Lcd "          "
         End If
         If Linhg_led = 0 Then
            Locate 1 , 20 : Lcd " "
         Else
            Locate 1 , 20 : Lcd Chr(4)
         End If
         Lowerline : Lcd "cіeїoіo№ гeЅД " ; Linhg_time_caunt ; "А "       ' Locate 4 , 1 световой день  ч
           rcall Flash_light

         If Zaderzhka_500_ms > 10 Or Zaderzhka_500_ms = 0 Then
            '  rcall Zapros_izmereniya_ds18b20
             rcall Opros_id_ds18b20
            Zaderzhka_500_ms = 0
         Else
            Waitms 100
         End If
         Incr Zaderzhka_500_ms
         If Culler_onoff = 255 Then
            Rcall Allarm_temperatura
         Else
            Reset Culler1
            Reset Culler2
            Reset Culler3
         End If

      Case 2
               ' установка часов
         rcall Sub_edit_time
      Case 3
                        ' выбор светового дня
         rcall Sub_edit_led
      Case 4
         rcall Sub_edit_temp
   End Select

      Debounce Button_menu , 0 , Knopka_menu , Sub
Loop
End


   '*******************************************************************************
  Sub Flash_light :                                         ' реле времени

   Lh = Linhg_hour_satr + Linhg_time_caunt
   A = Linhg_hour_satr - 1
   B = Lh + 1
   If Lh > 24 Then Lh = 24
   If _hour = Linhg_hour_satr And _min >= Linhg_min_satr Then       ' включение света если часы больше старта таймера и меньше выбранного светового дня
      Linhg_on = 1                                          'включение света
      Set Rl_light
   Else
      If _hour > Linhg_hour_satr And _hour < Lh Then
         Linhg_on = 1                                       'включение света
         Set Rl_light
      Else
         If _hour = Lh And _min <= Linhg_min_satr Then
            Linhg_on = 1                                    'включение света
            Set Rl_light
         Else
            Linhg_on = 0
            Reset Rl_light
         End If
      End If
  End If
 ' If Linhg_led > 0 Then
      If _hour = A And _min >= Linhg_min_satr Then          ' включение светодиодной подсветки за час до   старта таймера на час и   ' включение светодиодной подсветки  на час после отключения основного света
         Set Rl_light_led
      Else
         If _hour = Linhg_hour_satr And _min < Linhg_min_satr Then
            Set Rl_light_led
         Else
            If _hour = Lh And _min >= Linhg_min_satr Then
               Set Rl_light_led
            Else
               If _hour = B And _min < Linhg_min_satr Then
                  Set Rl_light_led
               Else
                  Reset Rl_light_led
               End If
            End If
         End If
      End If
 'End If
  End Sub





  '*******************************************************************************
  Sub Pervoe_vklyuchenie:
          Cls
          Lowerline : Lcd "    ЁEPB®¦ 3AЁ©CK"               ' первый запуск
          Waitms 3000
          rcall Zapros_kolichestva_ds18b20
          rcall Save_eeprom_id_ds18b20
        '  Cls
          Lowerline : Lcd " ¤aѕoјЅё»ё  aгpeca"              'Запомнили адреса
          Thirdline : Lcd "     " ; Kolichestvo_ds18b20 ; " гaїАёєoі  "
          Waitms 3000
          rcall Reading_eeprom_id_ds18b20
          Lowerline : Lcd "       «їeЅёe      "
          Thirdline : Lcd "       aгpecoі     "

          Waitms 3000
          1_vklyuchenie = 50
          Writeeeprom 1_vklyuchenie , 1
          Waitms 10
   Cls
  End Sub
'**************



'-------------------------------------------------------------------------------
Function Zapros_kolichestva_ds18b20() As Integer
   '   For A = 1 To 5                                        'моргаем в цикле, на LCD 3 раза
        Waitms 250
'=============================================
          Kolichestvo_ds18b20 = 1wirecount()                'Запрос количества датчиков Ds18b20 на линии
'=============================================
          Lowerline
          Lcd "       Ha№гeЅo     "                         'Печатаем на LCD "Найдено"
          Thirdline
          Lcd "   " ; Kolichestvo_ds18b20 ; " їepјo гaїАёєa"' Rs Ds18b20 "       'Печатаем на экране количество датчиков на линии
          Waitms 500                                        'Пауза ~ 750ms
   '  Next                                                   'Повторить
     Wait 1                                                 'Пауза ~ 2s
     Cls
  End Function
'---------------------------



 '*******************************************************************************    включения  вентиляторов
Sub Allarm_temperatura

   If Temperatura(1) >= 28 And Temperatura(1) < 30 Then     'включения вентилятора для 200л аквариума   при 28 градусах
      Incr Ani_temp(1)
      Locate 3 , 19

      Lcd " " ; Chr(ani_temp(1))
      Set Culler1
     Reset Culler2
      If Ani_temp(1) >= 3 Then Ani_temp(1) = 1
   Else

      If Temperatura(1) >= 30 Then                          'включения двух вентиляторов для 200л аквариума     при 30 градусах
         Incr Ani_temp(1)
       Set Culler2
       Set Culler1
         Locate 3 , 19
         Lcd Chr(ani_temp(1)) ; Chr(ani_temp(1))
         If Ani_temp(1) >= 3 Then Ani_temp(1) = 1
      Else

         Locate 3 , 19 : Lcd "  "
         Reset Culler1
         Reset Culler2
      End If
   End If

   '--------------------------------
   If Temperatura(2) >= 28 Then                             'включения вентилятора для 100л аквариума   при 28 градусах
      Incr Ani_temp(2)
      Set Culler3
      Locate 4 , 20

      Lcd Chr(ani_temp(2))
      If Ani_temp(2) >= 3 Then Ani_temp(2) = 1
      Else
      Locate 4 , 20 : Lcd " "
       Reset Culler3
   End If
End Sub
'**************




'-------------------------------------------------------------------------------
  Zapros_izmereniya_ds18b20:                                'запускаем опрос всех датчиков
    1wreset
    1wwrite &HCC                                            ' Выдаем команду чтения ПЗУ
    1wwrite &H44                                            ' Запуск измерения
  Bitwait Ds18b20 , Set                                     'Ждем сигнала датчика об окончании преобразования
   Waitms 350                                               'Ждем окончания преобразования
  Return
'-----------



'*******************************************************************************
'-------------------------------------------------------------------------------
  Sub Opros_id_ds18b20                                      'Подпрограмма опроса Ds18b20
'-------------------------------
Aqwanumb = 1
    X = 3 : 1wreset : 1wverify 1_id_ds18b20(1)              ': Y = 1  '1 ds18b20 выводим на первой(Х=1) строчке дисплея
    If Err = 0 Then
      Rcall Preobrazovanie_temperature
      Temperatura(1) = T_celye
    Else
      Error_ds18b20
    End If
'-------------------------------
Aqwanumb = 2
    X = 4 : 1wreset : 1wverify 2_id_ds18b20(1)              ': Y = 1  '2 ds18b20 выводим на первой(Х=1) строчке дисплея
    If Err = 0 Then
      Rcall Preobrazovanie_temperature
      Temperatura(2) = T_celye
    Else
      Error_ds18b20
    End If
  End Sub                                                   'Выходим из подпрограммы опроса Ds18b20
'-------------------------------------------------------------------------------
'*******************************************************************************




'-------------------------------------------------------------------------------
  Sub Preobrazovanie_temperature:                           'Подпрограмма считывания температуры
'--------------------------------
    1wwrite &HBE                                            'Запрос на чтение памяти
    Byte0 = 1wread()                                        'Читаем нулевой байт
    Byte1 = 1wread()                                        'Читаем первый байт
  If Byte1 > 248 Then                                       'Проверка на отрицательность температуры
    Byte0 = &H101 - Byte0
    Byte1 = &HFF - Byte1
    Znak_temperatura = "-"                                  'Знак "-"
  Else
    Znak_temperatura = "+"                                  'Вместо знака "+", ставим пробел
  End If
    T0 = Byte0 * 0.0625                                     ' Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
    T1 = Byte1 * 16                                         ' Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)
    T0 = T0 + T1                                            ' Формируем результат для вывода на дисплей
    T_celye = T0                                            'Убираем дробну часть(все после запятой)
    T_celye_lcd = Str(t_celye)                              'Делаем строковую переменную, для форматирования вывода на LCD
    T_celye_lcd = Format(t_celye_lcd , "00")                'Форматирование вывода на LCD
    If T_celye = 0 Then Znak_temperatura = " "
    T0 = T0 - T_celye                                       'Убираем все до запятой
    T0 = T0 * 10                                            'Делаем десятые градуса
    T_desyatye = T0                                         'Убираем дробну часть(все после запятой)
    T_desyatye_lcd = Str(t_desyatye)
    If T_celye > 99 Then Znak_temperatura = ""              'Если больше 99 градусов, сдвигаем в лево на 1 знак(для выравнивания показаний)
'--------------------------------
    Temperatura_lcd = Chr(5) + " " + Znak_temperatura + T_celye_lcd + "." + T_desyatye_lcd + Chr(1) + "C "
   rcall Displey_lcd
  End Sub
'-------------------------------------------------------------------------------
'*******************************************************************************





'*******************************************************************************
'-------------------------------------------------------------------------------
  Sub Displey_lcd:
'-----------------
Select Case Aqwanumb
Case 1
    Locate X , 1 : Lcd Chr(6) ; "200»  " ; Temperatura_lcd
Case 2
    Locate X , 1 : Lcd Chr(6) ; "100»  " ; Temperatura_lcd
End Select
'---------
End Sub
'----------------------------








  '-------------------------------------------------------------------------------
  Init_temperatura:
'------------------
     E = 0 : X = 1                                          ': Y = 1
     1wreset : 1wverify 1_id_ds18b20(1)                     ' Сброс линии  ' Обращаемся именно к этому датчику
   If Err = 0 Then
     E = E + 1
     Locate X , 1 : Lcd " 1 Sensor Ok "
   Else
     D = 1
     Sensor_not_found
   End If
'---------------------------------------------------
     X = 2                                                  ': Y = 1
     1wreset : 1wverify 2_id_ds18b20(1)                     ' Сброс линии  ' Обращаемся именно к этому датчику
   If Err = 0 Then
     E = E + 1
     Locate X , 1 : Lcd " 2 Sensor Ok "
   Else
     D = 2
     Sensor_not_found
   End If


   Wait 1 : Cls

'---------------------------------------------------
   1wreset                                                  ' Сброс линии
   1wwrite &HCC                                             ' Обращение к всем датчикам на линии
   1wwrite &H44                                             ' Запуск холостого измерения
'---------------------------------------------------
If E = Kolichestvo_ds18b20 Then
   Lowerline : Lcd "     Bce гaїАёєё    "                   '"Bce coxpaЅeЅЅГe     " "Все сохраненные  "
   Thirdline : Lcd "їeјѕepaїypГ  Ѕa№гeЅГ"                   '"гaїАёєё їeјѕepaїypГ " "датчики температуры"
  ' Thirdline : Lcd "Ѕa№гeЅГ             " ' "найдены
Else
 '  Upperline : Lcd "         " ; E ; "         "            'Upperline  1 строка, Lowerline  2 строка, Thirdline  3 строка, Fourthline 4 строка
 '  Lowerline : Lcd "  sensors  Ds18b20  "                   'Upperline  1 строка, Lowerline  2 строка, Thirdline  3 строка, Fourthline 4 строка
 '  Thirdline : Lcd "       found        "                   'Upperline  1 строка, Lowerline  2 строка, Thirdline  3 строка, Fourthline 4 строка
rcall Poisk_id_ds18b20
   End If

'---------------
  Wait 3 : Cls
'---------------
  Return













  '-------------------------------------------------------------------------------
  Error_ds18b20:
 ' Err_count
  If Err_count > 2 Then
       Locate X , 8 : Lcd Chr(5) ; "  NO SIG "
     Err_count = 0
     End If
  Incr Err_count
  '   Waitms 250
  Return


  Sensor_not_found:
'-------------------------------
   '  For A = 1 To 3
   '    Locate X , Y : Lcd "                    "
   '      Waitms 500

         Locate X , 1 : Lcd " " ; D ; " CeЅcop Ѕe Ѕa№гeЅ"   '; " Cенсор не найден "
   '      Waitms 500
   '  Next A
'-------------------------------

  Return




 '*******************************************************************************
  Sub Poisk_id_ds18b20:
'-------------------------------
   3_id_ds18b20(1) = 1wsearchfirst()
 ' Waitms 500
  Cls


  Lowerline : Lcd "   Ёoёck гaїАёkoі"                       ' поиск датчиков
  Locate 3 , 5
  For A = 1 To 12
     Waitms 100
 Lcd "-"
  Next A

   4_id_ds18b20(1) = 1wsearchnext()

   Waitms 500


C = 0
      For A = 1 To Kolichestvo_ds18b20                      'Kolichestvo_ds18b20
      For B = 1 To 8

If 3_id_ds18b20(b) <> 1_id_ds18b20(b) And 3_id_ds18b20(b) <> 2_id_ds18b20(b) Then C = C + 1
If 4_id_ds18b20(b) <> 1_id_ds18b20(b) And 4_id_ds18b20(b) <> 2_id_ds18b20(b) Then C = C + 1

      Next B
    Next A

If C > 0 Then
   Cls
   Upperline
   Lcd "    6Г»a ·aјeЅa "                                   'Было замена  датчика
   Lowerline
   Lcd "      ceЅcopa"
   Waitms 1500
  'End If
  'If C = 8 Then
  'Cls
  '  Locate 1 , 1
  ' Lcd "    6Г»a ·aјeЅa "                                     'Было замена 1 датчика
  ' Locate 2 , 1
  ' Lcd "     2 ceЅcopa"                                       'Было замена 2 датчика
  '  Waitms 1500
  'End If
   'If C > 0 Then
   1_vklyuchenie = 1
   Writeeeprom 1_vklyuchenie , 1
 End If
 End Sub
'*******************************************************************************











'*******************************************************************************
'********* Подпрограмма поиска и записи ID DS18B20 в EEPROM контроллера ********
'*******************************************************************************
'-------------------------------------------------------------------------------
  Sub Save_eeprom_id_ds18b20                                'Подпрограмма поиска и записи ID DS18B20 в EEPROM контроллера
'----------------------------
'========= Первый датчик ==========
  Id_ds18b20(1) = 1wsearchfirst()                           'Посылаем запрос и получаем ответ в виде 8-ми байтного адреса первому датчику
'==================================
    Adres_id_ds18b20 = 10                                   'Начинаем с 10 адреса (просто для удобства (первый датчик - 10 адрес, второй датчик - 20 адрес и т.д. ))
      For B = 1 To 8                                        'Работаем с 8 байтами первого, считанного ID DS18B20
        Writeeeprom Id_ds18b20(b) , Adres_id_ds18b20        'Записываем в установленную ранее ячейку памяти контроллера
  '1_id_ds18b20(b) = Id_ds18b20(b)
           Waitms 5                                         'Пауза ~ 5ms
        Incr Adres_id_ds18b20                               'Увеличиваем адрес на 1
      Next B                                                'Повторяем для всего значения считанного ID  первого датчика

    Waitms 50

'------- Следующие  датчики --------
 For A = 2 To Kolichestvo_ds18b20
'===================================
    Id_ds18b20(1) = 1wsearchnext()                          'Посылаем запрос и получаем ответ в виде 8-ми байтного адреса следующему датчику
'===================================
      Adres_id_ds18b20 = Adres_id_ds18b20 + 2               'Увеличиваем адрес на 2, что-бы получить следующий, целый десяток(для удобства)
        For B = 1 To 8                                      'Работаем с 8 байтами следующего, считанного ID DS18B20
 '2_id_ds18b20(b) = Id_ds18b20(b)
          Writeeeprom Id_ds18b20(b) , Adres_id_ds18b20      'Записываем в установленную ранее ячейку памяти контроллера
            Waitms 5                                        'Пауза ~ 5ms
          Incr Adres_id_ds18b20                             'Увеличиваем адрес на 1
        Next B                                              'Повторяем для всего значения считанного ID следующего датчика

    Waitms 50

      Next A                                                'Переходим к поиску следующего датчика
     A = A - 1
    Number_saved_ds18b20 = A
   Writeeeprom Number_saved_ds18b20 , 5

'----------
  End Sub                                                   'Выходим из подпрограммы поиска и записи ID DS18B20 в EEPROM контроллера
'-----------------------------





                     '
'*******************************************************************************
'********* Подпрограмма чтения ID DS18B20 из EEPROM контроллера ****************
'*******************************************************************************
'-------------------------------------------------------------------------------
  Sub Reading_eeprom_id_ds18b20
'-------------------------------
'  Local A As Byte , B As Byte
'-------------------------------
  Adres_id_ds18b20 = 10
'-----------------------
    For A = 1 To Kolichestvo_ds18b20                        'Kolichestvo_ds18b20
      For B = 1 To 8
        Readeeprom Id_ds18b20(b) , Adres_id_ds18b20
          Select Case Adres_id_ds18b20
            Case 10 To 19 : 1_id_ds18b20(b) = Id_ds18b20(b)
            Case 20 To 29 : 2_id_ds18b20(b) = Id_ds18b20(b)
            Case Else
          End Select
        Adres_id_ds18b20 = Adres_id_ds18b20 + 1
      Next B
     Adres_id_ds18b20 = Adres_id_ds18b20 + 2
    Next A
   A = A - 1
'----------
  End Sub                                                   'Выходим из подпрограммы поиска и записи ID DS18B20 в EEPROM контроллера
'-------------------------------------------------------------------------------


'----------РАБОТА С МЕНЮ

'-----------------------------выбор светового дня--------------------------------------------------
  Sub Sub_edit_led()                                        '2. Световой день
                Waitms 100
         If Zaderzhka_50_ms >= 20 Then
            If Zaderzhka_50_ms >= 22 Then
               Edit_menu = 1
               Upperline : Lcd "---Cіeїoіo№  гeЅД---"       '2. Световой день
              'Locate 2 , 7 : Lcd Time$
               Zaderzhka_50_ms = 22
              ' Edit_time = 1
              ' Kyrsor_lcd = ">"
               T_desyatye_lcd = Str(linhg_hour_satr )
               T_desyatye_lcd = Format(t_desyatye_lcd , "00")
               Znak_temperatura = Str(linhg_min_satr )
               Znak_temperatura = Format(znak_temperatura , "00")
               Temperatura_lcd = T_desyatye_lcd + ":" + Znak_temperatura + ":00"
               Locate 2 , 2 : Lcd "cіeї іє»: " ; Temperatura_lcd       ' свет вкл: ХХ:ХХ:ХХ
               Locate 3 , 2 : Lcd "Cіeїoіo№ гeЅД: " ; Linhg_time_caunt ; "А "       ' световой день Х ч
               If Linhg_led = 0 Then
                  Locate 4 , 2 : Lcd "LED ѕoгcіeїєa: OFF"   ' LED подсветка  : OFF
               Else
                  Locate 4 , 2 : Lcd "LED ѕoгcіeїєa: ON "   ' LED подсветка  : ON
               End If
               Cur_x = Edit_time : Gosub Set_cursor
               'Locate Edit_time , 1 : Lcd Kyrsor_lcd

               If Кнопка = 0 Then                           ' выбор подменю
               Return_menu = 0
                  Waitms 500
                  Incr Edit_time
                  If Edit_time > 4 Then Edit_time = 2
               End If

               If Edit_time = 3 Then
                  Cur_x = 2 : Gosub Clear_cursor
                 ' Locate 2 , 1 : Lcd " "                    'выбор светового дня
                  If Button_hour = 0 Then
                     Waitms 250
                     Incr Linhg_time_caunt
                     If Linhg_time_caunt > 13 Then Linhg_time_caunt = 8
                  End If
               End If

               If Edit_time = 4 Then
                  Cur_x = 3 : Gosub Clear_cursor
                          '       Locate 3 , 1 : Lcd " "     'выбор подсветки дня
                  If Button_hour = 0 Then
                     Waitms 250
                     Toggle Linhg_led
                  End If
               End If


               If Edit_time = 2 Then
                  Cur_x = 4 : Gosub Clear_cursor
                '   Locate 4 , 1 : Lcd " "                   'выбор часов
                  If Button_hour = 0 Then
                     Waitms 250
                     Incr Linhg_hour_satr
                     If Linhg_hour_satr >= 24 Then Linhg_hour_satr = 0
                  End If

                  If Button_min = 0 Then
                  Return_menu = 0
                     Waitms 200
                     Incr Linhg_min_satr
                     If Linhg_min_satr >= 60 Then Linhg_min_satr = 0
                  End If
               End If

            Else
               Incr Zaderzhka_50_ms
               Edit_time = 2
               Cls
            End If
         Else
            Incr Zaderzhka_50_ms
         End If

  End Sub
'-------------------------------------------------------------------------------
'--------------------------Установка часов-----------------------------------------------------
 Sub Sub_edit_time()

          Waitms 100
         If Zaderzhka_50_ms >= 20 Then
            If Zaderzhka_50_ms >= 22 Then
              Edit_menu = 1
              Upperline : Lcd "--©cїaЅoієa  Аacoі--"
              Locate 3 , 7 : Lcd Time$
               Zaderzhka_50_ms = 22
               Edit_time = 1
             If Button_hour = 0 Then
               Waitms 250
               Return_menu = 0
               Incr _hour
               If _hour >= 24 Then _hour = 0
             End If

             If Button_min = 0 Then
               Waitms 200
               Return_menu = 0
               Incr _min
               If _min >= 60 Then _min = 0
             End If

            Else
               Incr Zaderzhka_50_ms
               Cls
            End If
         Else
            Incr Zaderzhka_50_ms
         End If

 End Sub
'------------------------------Tepmo pele-------------------------------------------------

Sub Sub_edit_temp()

         Waitms 100
         If Zaderzhka_50_ms >= 20 Then
            If Zaderzhka_50_ms >= 22 Then
               Locate 1 , 1 : Lcd "-----Tepјope»e-----"
               Edit_menu = 1
               Zaderzhka_50_ms = 22
               If Culler_onoff = 0 Then
                  Thirdline : Lcd ">Ox»o¶гeЅёe: OFF"        ' охлождение офф
               Else
                  Thirdline : Lcd ">Ox»o¶гeЅёe: ON "        ' охлождение он
               End If

                  If Button_hour = 0 Or Button_min = 0 Then
                     Waitms 250
                     Toggle Culler_onoff
                  End If


            Else
               Incr Zaderzhka_50_ms
               Edit_time = 2
               Cls
            End If
         Else
            Incr Zaderzhka_50_ms
         End If



 End Sub

 ' ---------------------------------------------------------------------------
 ' -----------------основное меню-------------------------------
 ' ---------------------------------------------------------------------------
 Knopka_menu:
   Waitms 400
   If Edit_menu = 0 Then
   Return_menu = 0
      Select Case Menu
         Case 0
             Upperline : Lcd "---OCHOBHOE MEH°--- "         '"---ОСНОВНОЕ МЕНЮ--- "
             Lowerline : Lcd "  1. ©cїaЅoієa Аacoі"         '"  1. Установка часов"
             Thirdline : Lcd "  2. Cіeїoіo№ гeЅД  "         '2. Световой день
             Fourthline : Lcd "  3. Tepјope»e      "        ' 3. Tepmo pele
         Case 1
         Cur_x = 2
            ' Locate 2 , 1 : Lcd ">"                         '"  1. Установка часов"
             Gosub Set_cursor
         Case 2
         Cur_x = 2
         Gosub Clear_cursor
         Cur_x = 3
         Gosub Set_cursor
                     '  Locate 2 , 1 : Lcd " "                         '"  1. Установка часов"
          '   Locate 3 , 1 : Lcd ">"                         '2. Световой день
         Case 3
          Cur_x = 3
         Gosub Clear_cursor
         Cur_x = 4
         Gosub Set_cursor
          '   Locate 3 , 1 : Lcd " "                         '2. Световой день
           '  Locate 4 , 1 : Lcd ">"                         ' 3.Tepmo pele
      End Select
      If Menu = 4 Then
      Gosub Return_to_programm                              'выход с  меню по нажатию кнопки меню
      Else
         Incr Menu
      End If
   End If

   If Edit_menu = 1 Then
   Gosub Return_to_programm                                 'выход с редактирования меню по нажатию кнопки меню
   End If
  ' Gifr = 64
 Return



 Return_to_programm:                                        ' возврат из меню
      Waitms 1000
      Cls
      Menu = 0
      Zaderzhka_500_ms = 0
 Return



Clear_cursor:
Locate Cur_x , 1 : Lcd " "
Return

Set_cursor:
Locate Cur_x , 1 : Lcd ">"
Return


End

p/s  в прщессе оптисизации я понял что оператор Locate жрет больше места на 4 байта чем Lowerline или Upperline  а  оператор Cls вообще прожорлив

0

2

да , забыл сказать что меню работает через одно место :tomato:

0

3

Привет!
Что памяти мало, бывает?

Самое простое решение, взять МК с большим количеством памяти: Atmega168A (16 кб), Atmega328P (32 кб)!

Другой вариант:
Если Вам надо только 2 датчика Ds18b20, повесьте их на разные ноги МК - освободится много памяти!

Если Вам нужны часы, как собираетесь бороться с пропаданием света и последующим сбиванием времени?

Отредактировано sasha_1973 (2013-08-17 19:39:01)

0

4

беда в том что у меня есть в наличии только Atmega8A  а до ближайшего города с магазином радио товаров 40 км

а поподробнее про второй вариант с Ds18b20 на разных ногах МК? ато я пробовал - не пошло

а по поводу часов - поставить батарейку на питание проца + компрессора (воздух для рыбок) подключены через ИБП  и к нему будет подключен сей девайс (хотя  про проблемы со светом забыли еще при дедушке Ленине  :crazyfun: )

0

5

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

а поподробнее про второй вариант с Ds18b20 на разных ногах МК? ато я пробовал - не пошло


Принцип работы с датчиками тот-же. Просто вешаете на разные ноги МК. Актуально при небольшом количестве Ds18b20.

Чуть позже будет исходник и симуляция в "Протеус".

Отредактировано sasha_1973 (2013-08-18 07:05:00)

0

6

Откажитесь от использования "Declare Sub" - эта штука памяти жрет, да и тонко настраивать нужно:   $hwstack, $swstack, $framesize. Может подглюкивать.
Функция/оператор "Locate" нужно по возможности чтобы был в коде один, при каждом его появления компилятор генерит каждый раз отдельно окружение и подпрограмму (заново), от сюда столько и растраты места. Постарайтесь оптимизировать код так, чтобы "Locate" был один, два во всем коде (используйте подпрограммы (GOSUB/RETURN) с передачей данных через одни и те же переменные). Кстати так со всеми функциями в баскоме, компилятор не умеет оптимизировать код по длине...

Отредактировано RDW (2013-08-18 12:45:38)

0

7

Как и обещал, выкладываю исходник и эмуляцию.
Это обобщенный вариант, в Вашем случае его можно уменьшить на 10%.

В данном исполнении (время, 2 датчика, вывод на LCD, вывод по USART), занимает 35% объема памяти МК).
Что непонятно спрашивайте.

Думаю добавить обработку кнопок и нагрузки, или ещё то, в чем есть необходимость труда не составит.
Если USART не нужен, просто удалите или закомментируйте соответствующую подпрограмму.

! Внимание !
В иходнике используется упрощенный расчет температуры - только положительные значения!

Исходник, эмуляция - скачать

Работа в "Протеус"
http://s5.uploads.ru/t/GtJSf.jpg

Отредактировано sasha_1973 (2013-08-18 13:26:14)

0

8

Спасибо! работает! использование FlashROM  сократил аж на 3кб!

правда после того как пересадил датчики на разные ноги МК , не захотело работать,  но после долгих танцев с бубном, магических песнопений и долгого обкуривания ПК заработало!
оказалось, если в протеусе у датчика Ds18b20 поставить резистор 4.7к между ногой DQ и питанием то переменная    T2 (1)  после выполнения команды чтения датчика   T2 (1) = 1wread(2 , Pinb , 0 )  принимает значение -1 и все. :canthearyou:  но если этот  резистор 4.7к поменять на резистор с волшебной надписью PULLUP то все работает  :dontknow:
причем прикол в том что если всего один датчик на одной ноге  с резистором 4.7к  читается нормально командами    Byte0 = 1wread()    :    Byte1 = 1wread()   

да еще хотел спросить, а почему вы не использовали софтовые часы? и почему многие стараются не поьзоваться  оператором Time$ = "10:20:00"?

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

Откажитесь от использования "Declare Sub" - эта штука памяти жрет, да и тонко настраивать нужно:   $hwstack, $swstack, $framesize. Может подглюкивать.
Функция/оператор "Locate" нужно по возможности чтобы был в коде один, при каждом его появления компилятор генерит каждый раз отдельно окружение и подпрограмму (заново), от сюда столько и растраты места. Постарайтесь оптимизировать код так, чтобы "Locate" был один, два во всем коде (используйте подпрограммы (GOSUB/RETURN) с передачей данных через одни и те же переменные). Кстати так со всеми функциями в баскоме, компилятор не умеет оптимизировать код по длине...

Отредактировано RDW (Сегодня 11:45:38)

ммм... поменял  все Declare Sub на GOSUB/RETURN  обьем данных в FlashROM   не уменьшился ни на байт , может они SRAM  пожирают?

0

9

Скиньте в личку Ваш исходник с эмуляцией.

По поводу "Протеус" - Вы скорее всего используете аналоговую модель резистора, а эмулируете цифровую модель (ds18b20), есть элементы для симуляции, а есть для разводки печатных плат или графического обозначения. Если выбирать правильные и по возможности заменять на Model Primitive, возьмите модель "resistor" (Analog resistor primitive), и все у Вас заработает, модель "PULLUP" или "PULLDOWN" как раз и являются веше указанными, только их алгоритм эмуляции еще проще.

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

На счет - "многие стараются не пользоваться", дело в том, что не известно, что там Bascom накомпилирует, я думаю будет лучше, если видеть, что происходит с исходником, наверное так-же думают и другие.

Отредактировано sasha_1973 (2013-08-19 07:47:23)

0

10

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

Спасибо! работает! использование FlashROM  сократил аж на 3кб!

Что-то маловато освободилось, а точнее, практически ничего?!

Ваши исходник+эмуляция в личку или на почту!

Отредактировано sasha_1973 (2013-08-19 07:48:55)

0

11

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

ммм... поменял  все Declare Sub на GOSUB/RETURN  обьем данных в FlashROM   не уменьшился ни на байт , может они SRAM  пожирают?

Отказ от "Declare Sub" - повысит надежность и место в SRAM.
А оптимизация относительно "Locate" - должна освободить место. С "print"-ом такая же штука.

0

12

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

Отказ от "Declare Sub" - повысит надежность и место в SRAM.
А оптимизация относительно "Locate" - должна освободить место. С "print"-ом такая же штука.

Declare Sub транслируется компилятором в Gosub если не задавать переменных.
У AVR хреново с математикой, все нецелочисленные типы жрут память.
Простая замена
Dim T As Single , T0 As Single , T1 As Single               'Переменные для преобразования температуры
на
Dim T As Word , T0 As Word , T1 As Word               'Переменные для преобразования температуры
уменьшает код на 7%
Конструкцию 
T0 = Byte0 * 0.0625 умный компилятор превратит в чистый сдвиг с отбросом ненужного, но лучше явно заменить на
    Shift Byte0 , Right , 4
    Shift Byte1 , Left , 4
или можно попробовать
T0 = Makeint(Byte0 , Byte1)

Так же у AVR очень мало команд косвенного обращения к ОЗУ, собственно всего одна и одна регистровая пара, от этого BasCom раздувает код при работе с массивами, лучше использовать две переменных, чем конструкцию типа
Dim Temperatura(2) As Byte, ото позволит экономить несколько байт при каждом обращении. Вообще переменных на мой взгляд очень много. Тяжелых переменных, строковых.

0

13

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

Постарайтесь оптимизировать код так, чтобы "Locate" был один, два во всем коде (используйте подпрограммы (GOSUB/RETURN) с передачей данных через одни и те же переменные)

Я вот тут попробовал. Мега8. Заменил в 12-ти местах одинаковый Locate 2 , 8 на подпрограмму (Gosub) и в 9 местах X,Y вынес в переменные и тоже через Gosub. Как было 89%, так и осталось. Правда, размер в байтах не смотрел.

0

Похожие темы

Никогда

Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Управление аквариумом на atmega8 , помогите с оптимизацией кода