У моих знакомых стоит вендинговый аппарат для продажи цветов. Устройство примитивное. Вращается вал на котором в два ряда расположены ячейки для цветов и два окна, верхнее и нижнее для выдачи покупок.
Управляется всё это от Raspberry Pi 4. Есть WiFi и облачный сервис.
Но вот случилось такая оказия. Когда автомат останавливается и открывается окно можно забрать свой букет и, прокрутив стойку, забрать и другие.
Встал вопрос кто виноват и что делать. Придумали такую штуку. На вал одеваем звёздочку, ставим актуатор и при открытии верхнего или нижнего окна актуатор выдвигается и стопорит вал.
При закрытии окна он естественно задвигается и всё работает дальше.
Необходимо отметить, что окна не могут открыться одновременно. Открывается либо верхнее, либо нижнее в зависимости от того, какой букет выбрал покупатель. И ещё, окно открывается только тогда, когда нужный букет подъехал к нему, т. е. вал останавливается.
Быстренько накидал плату и впервые решил попробовать на ЛУТ, а фоторезист. Получилось просто замечательно. Теперь ЛУТ в моём арсенале отсутствует. Результат чуть ниже.
Коротенько о схеме.
На вход подаются 4 сигнала с бесконтактных концевиков окон. Соответственно с них и будем снимать сигналы. Чтобы не заморачиваться с транзисторными ключами решил использовать оптроны, коих немного завалялось. Контроллер Atmega88. Использовал только 12% памяти. Сигналы управления подал на двухканальную плату управления двигателем на базе L298N.
У него на борту есть стабилизатор на 5 вольт. Поэтому Он сам питается от 12, а на МК с него подаётся 5.
Естественно раз мотор один, то и канал использую один. В общем я его слепила из того, что было. Самое главное, что работает, а что ещё нужно.
Сигналы с концевиков обрабатываются в прерываниях, а остальное МК спит.
В данном актуаторе ход 100 мм., скорость 10 мм/сек. Нам столько не нужно, поэтому вылет регулируется стандартным Waitms.
Решил разместить здесь, может кому нужно будет.
https://forumupload.ru/uploads/0000/25/b8/819/t699832.jpg
Плата без драйвера двигателя
https://forumupload.ru/uploads/0000/25/b8/819/t895075.jpg
Плата в сборе.
https://forumupload.ru/uploads/0000/25/b8/819/t972844.jpg
https://forumupload.ru/uploads/0000/25/b8/819/t126028.jpg
Коротенькое видео.

Теперь коротко об изготовлении платы при помощи фоторезиста.
Начитавшись страшилок о трудностях в интернете я сомневался в конечном успехе мероприятия, но решил попробовать.
В общем ничего страшного не оказалось. Нужно только соблюдать несколько простых правил:
1. Качественный и максимально чёрный фотошаблон.
2. Тщательное обезжиривание платы. Я не пользуюсь наждачкой. Пемолюкс и губка для посуды со стороны, где тёрка. Потом Фейри или любая другая дребедень. Если вода не скатывается в комочки, то всё отлично.
3. Хороший прижим фотошаблона к плате по всей поверхности.
4. Светил УФ лампой 10 минут.
5. Небольшая концентрация кальцинированной соды для проявки. Примерно чайная ложка на литр.
6. Опускаем экспонированную плату в соду и мягкой кисточкой потихоньку смываем ненужное. Периодически промываем водой и смотрим где остался фоторезист. Его хорошо видно после промывки. Опять в проявитель и кисточка.
Травление обычное. Только желательно в горячем растворе. Так быстрее травится и нет подтравок под фоторезист.
Вот и все хитрости. Вполне по силам сделать дорожки 0.1 мм.
Несколько фото.
https://forumupload.ru/uploads/0000/25/b8/819/t347707.jpg
Шаблон
https://forumupload.ru/uploads/0000/25/b8/819/t877763.jpg
Проявленный фоторезист
https://forumupload.ru/uploads/0000/25/b8/819/t231772.jpg
Готовая плата
https://forumupload.ru/uploads/0000/25/b8/819/t248017.jpg
Дорожки 0,8 мм

Код:
$regfile = "m88def.dat"                                     'Контроллер
$crystal = 8000000                                          'Определение частоты кварца
$hwstack = 8                                                ' hardware stack
$swstack = 8                                                'software stack
$framesize = 32                                             'frame space
CONFIG SUBMODE = NEW
'----------------------------------------------- Конфигурация --------------------------------
'Конфигурация портов светодиода
Config portd.5 = Output                                     'Выход светодиода открытие верхнего окна   LED1
Config portd.6 = Output                                     'Выход светодиода закрытие верхнего окна   LED2
Config portd.7 = Output                                     'Выход светодиода открытие нижнего окна    LED3
Config portb.0 = Output                                     'Выход светодиода закрытие нижнего окна    LED4
LED1 Alias portd.5
LED2 Alias portd.6
LED3 Alias portd.7
LED4 Alias portb.0
'Конфигурация порта двигателя
Config portc.1 = Output                                     'Выход на двигатель +
Config portc.0 = Output                                     'Выход на двигатель -
Dplus Alias portc.1
Dminus Alias portc.0
'Конфигурация прерываний
CONFIG INT0 = Rising                                        'Прерывание от верхнего концевика нижнего окна
CONFIG INT1 = Rising                                        'Прерывание от нижнего концевика верхнего окна
PCICR = &B00000110                                          'Прерывания от PCIE1 и 2
pcmsk1 = &B00000100                                         'Прерывания от PCINT[10] (PC2). Прерывание от
                                                                                'нижнего концевика нижнего окна
pcmsk2 = &B00010000                                         'Прерывание от PCINT[20] (PD4). Прерывание от
                                                                               'верхнего концевика верхнего окна
'Разрешим прерывания
On Int0 TopDown NoSave                                      'Сработал верхний концевик нижнего окна
On Int1 DownTop NoSave                                      'Сработал нижний концевик верхнего окна
On pcint1 DownDown                                          'Сработал нижний концевик нижнего окна
On pcint2 TopTop                                            'Сработал верхний концевик верхнего окна
Enable int0
Enable int1
ENABLE INTERRUPTS
'--------------------------------------------- ПЕРЕМЕННЫЕ И КОНСТАНТЫ ---------------------------------------------------
Dim DownUp_Int , TopUp_Int as Byte                          'Флаги прерывания нижнего или верхнего концевиков верхнего окна
Dim TopDown_Int , DownDown_Int as Byte                      'Флаги прерывания верхнего или нижнего концевиков нижнего окна
Dim FlagTT as Byte                                          'Флаг состояния прерывния верхнего концевика верхнего окна
Dim FlagDD as Byte                                          'Флаг состояния прерывния нижнего концевика нижнего окна
Dim Port as Byte                                            'Для чтения состояния порта
Dim i as Byte
Dim Tcal as Word                                            'Время калибровки
Const T = 2000                                              'Время работы актуатора в мс
'------------------------------------------------------- ПРОГРАММА ----------------------------------------------------------------
'Старт
For i = 1 to 3
   Set Led1 : Set Led2 : Set Led3 : Set Led4
   Waitms 500
   Reset Led1 : Reset Led2 : Reset Led3 : Reset Led4
   Waitms 500
Next i
'Начальная калибровка.
'Выдвинем актуатор
Set Dplus : Reset Dminus                                    'Выдвигаем актуатор
Waitms T                                                    'Ждём
Reset Dplus : Reset Dminus                                  'выключаем мотор
Set Led1 : Set Led3 : Reset Led2 : Reset Led4               'Зажигаем светодиод открытия. Гасим светодиод закрытия
Wait 3
'Задвинем актуатор
Tcal = T * 5                                                'Время закрытия в пять раз больше времени открытия
Reset Dplus : Set Dminus                                    'Задвигаем актуатор
Waitms Tcal                                                 'Ждём
Reset Dplus : Reset Dminus                                  'выключаем мотор
Reset Led1 : Reset Led3 : Set Led2 : Set Led4               'Зажигаем светодиод закрытия. Гасим светодиод открытия
'Основная программа
Main:
'Сработал нижний концевик верхнего окна
   If DownUp_Int = 1 Then
      DownUp_Int = 0
      Disable Int0                                          'Запретим прерывание от верхнего концевика НИЗ
      Disable pcint1                                        'Запретим прерывание от нижнего концевика НИЗ
      Disable Int1                                          'Запретим прерывание от нижнего концевика ВЕРХ
      Disable pcint2                                        'Запретим прерывание от верхнего концевика ВЕРХ
      Set Dplus : Reset Dminus                              'Выдвигаем актуатор
      Waitms T                                              'Ждём
      Reset Dplus : Reset Dminus                            'выключаем мотор
      Set Led1 : Reset Led2                                 'Зажигаем светодиод открытия. Гасим светодиод закрытия
      Enable pcint2                                         'Разрешим прерывание от верхнего концевика ВЕРХ
   End If
'Сработал верхний концевик верхнего окна
   If TopUp_Int = 1 Then
      TopUp_Int = 0
      Disable Int0                                          'Запретим прерывание от верхнего концевика НИЗ
      Disable pcint1                                        'Запретим прерывание от нижнего концевика НИЗ
      Disable Int1                                          'Запретим прерывание от нижнего концевика ВЕРХ
      Disable pcint2                                        'Запретим прерывание от верхнего концевика ВЕРХ
      Reset Dplus : Set Dminus                              'Задвигаем актуатор
      Waitms T                                              'Ждём
      Reset Dplus : Reset Dminus                            'выключаем мотор
      Reset Led1 : Set Led2                                 'Гасим светодиод открытия. Зажигаем светодиод закрытия
      Enable INT1                                           'Разрешим прерывание от нижнего концевика ВЕРХ
      Enable Int0                                           'Разрешим прерывание от верхнего концевика НИЗ
   End If
'Сработал верхний концевик нижнего окна
   If TopDown_Int = 1 Then
      TopDown_Int = 0
      Disable Int0                                          'Запретим прерывание от верхнего концевика НИЗ
      Disable pcint1                                        'Запретим прерывание от нижнего концевика НИЗ
      Disable Int1                                          'Запретим прерывание от нижнего концевика ВЕРХ
      Disable pcint2                                        'Запретим прерывание от верхнего концевика ВЕРХ
      Set Dplus : Reset Dminus                              'Выдвигаем актуатор
      Waitms T                                              'Ждём
      Reset Dplus : Reset Dminus                            'выключаем мотор
      Set Led3 : Reset Led4                                 'Зажигаем светодиод открытия. Гасим светодиод закрытия
      Enable pcint1                                         'Разрешим прерывание от нижнего концевика НИЗ
   End If
'Сработал нижний концевик нижнего окна
   If DownDown_Int = 1 Then
      DownDown_Int = 0
      Disable Int0                                          'Запретим прерывание от верхнего концевика НИЗ
      Disable pcint1                                        'Запретим прерывание от нижнего концевика НИЗ
      Disable Int1                                          'Запретим прерывание от нижнего концевика ВЕРХ
      Disable pcint2                                        'Запретим прерывание от верхнего концевика ВЕРХ
      Reset Dplus : Set Dminus                              'Задвигаем актуатор
      Waitms T                                              'Ждём
      Reset Dplus : Reset Dminus                            'выключаем мотор
      Reset Led3 : Set Led4                                 'Гасим светодиод открытия. Зажигаем светодиод закрытия
      Enable INT1                                           'Разрешим прерывание от нижнего концевика ВЕРХ
      Enable Int0                                           'Разрешим прерывание от верхнего концевика НИЗ
   End If

   eifr = 0                                                 'Сбросим флаги прерываний INT 0 и INT1
   pcifr = 0                                                'Сбросим флаги прерываний PCINT1 и PCINT 2
   CONFIG POWERMODE = IDLE                                  'Уснём
   GoTo Main
   End
'------------------------------------------------------- ПРЕРЫВАНИЯ ----------------------------------------------------------------
'Прерывание от нижнего концевика верхнего окна
DownTop:
   $asm
      push R24
      in R24,SREG
      push R24
      LDI R24,1                                             'Установим флаг прерывания
      STS {DownUp_Int},R24
      pop R24
      out sreg , R24
      pop R24
   $end asm
Return
'Прерывание от верхнего концевика верхнего окна
TopTop:
  'Читаем порт D
   Port = pind AND 16                                       'Выделим пин прерывания
   If Port = 16 and FlagTT = 0 Then
      FlagTT = 1                                            'Сработал концевик по фронту
      TopUp_Int = 1
   Else
      FlagTT = 0                                            'Сработал концевик  по спаду
      TopUp_Int = 0
   End If
Return
'Прерывание от верхнего концевика нижнего окна
TopDown:
   $asm
      push R24
      in R24,SREG
      push R24
      LDI R24,1                                             'Установим флаг прерывания
      STS {TopDown_Int},R24
      pop R24
      out sreg , R24
      pop R24
   $end asm
Return
'Прерывание от нижнего концевика нижнего окна
DownDown:
  'Читаем порт С
   Port = pinC AND 4                                        'Выделим пин прерывания
   If Port = 4 and FlagDD = 0 Then
      FlagDD = 1                                            'Сработал концевик по фронту
      DownDown_Int = 1
   Else
      FlagDD = 0                                            'Сработал концевик  по спаду
      DownDown_Int = 0
   End If
Return

Отредактировано sva-don (2021-11-17 13:48:45)