Наливатор с ОЛЕД дисплеем , MP3-плееером, LED подсветкой , шаговиком или сервой.

Наливатор с ОЛЕД дисплеем , MP3-плееером, LED подсветкой , шаговиком или сервой.
ОБЩЕЕ ОПИСАНИЕ.
Наливатор на с дисплеем OLED , MP3 плеером, 3-мя режимами налива , светодиодной подсветкой , рассчитаный на максимум 6 рюмок.

Подробное описание подключения.

Контроллер
Вся конструкция тестировалась на ардуино нано.

nano.jpg

Распределение пинов:

0

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

1

Аппаратный сериал.

2

A энкодера

3

B энкодера

4

Кнопка энкодера

5

Канал управления адресной светодиодной лентой.

9

Канал управление сервоприводом

10

к RX плеера (через резистор 1к)

11

к TX плеера (через резистор 1к)

12

к BUSY плеера

13

Канал управление помпой

A0-A3

A4,А5
SDA, SCL

А6-А7
свободными остаются пины: 6, 7, 8. При смене сервопривода на шаговый двигатель они будут задействованы, а так же будет задействован пин 0 на концевик нулевого положения. 1-ый пин будет давать возможность выводить в монитор порта отладочные сообщения. Данный вид подключения пока реализован частично, рассчитан на микросхему ULN2003APC, которая часто идет в комплекте с шаговым двигателем 28BYJ-48.









Дисплей
Монохромный дисплей с разрешение 128х64
Подключение I2C, (А4 и А5 )
Скетч гарантированно поддержи
вает 2 дисплея: SH1106 1.3 дюйма и SSD1306 . По идее должен поддерживать графический ЖК дисплей 12864. Библиотека поддерживает и другие дисплеи.
1106.jpg1306.png12864.png
Библиотека U8glib.
В проект добавлены руссифицированные шрифты.
Настройка дисплея осуществляется выбором соотв. строки в файле silver_naliv_20.ino, строки 12-16
C++:
// выбор нужного драйвера дисплея
//U8GLIB_SH1106_128X64 Display(U8G_I2C_OPT_NONE);  // I2C / TWI
U8GLIB_SH1106_128X64 Display(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);  // Dev 0, Fast I2C / TWI
//U8GLIB_SSD1306_128X64 Display(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0); // I2C / TWI
//U8GLIB_SSD1306_128X64 Display(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
Распиновка дисплеев в моем случае не совпадает! Будьте внимательны при подключении.

Энкодер.
Для работы используется мини-библиотека encMinim.h, работает без аппаратного прерывания, но вполне надежно. Для управления используется клик кнопкой, повороты вправо и влево, повороты с нажатой кнопкой, а так же удержание кнопки, как отмена.
Опробовано 2 типа энкодеров:
enc2.pngenc1.png
Отличие подключения 1-го от 2-го заключается в подключении +5 в для второго, и некотором отличии в коде.
Изменение в необходимо сделать в файле encMinim.h
Для первого типа:
C++:
 /* pinMode2 (_clk, INPUT);
  pinMode2 (_dt, INPUT);
  pinMode2 (_sw, INPUT);
*/
  pinMode2 (_clk, INPUT_PULLUP);
  pinMode2 (_dt, INPUT_PULLUP);
  pinMode2 (_sw, INPUT_PULLUP);
Для второго типа:
C++:
  pinMode2 (_clk, INPUT);
  pinMode2 (_dt, INPUT);
  pinMode2 (_sw, INPUT);
  /*
  pinMode2 (_clk, INPUT_PULLUP);
  pinMode2 (_dt, INPUT_PULLUP);
  pinMode2 (_sw, INPUT_PULLUP);
  */

MP3 - плеер
В качестве плеера используется DFPlayer , он же MP3-TF-16P
DFPlayer.png
У плеера есть встроенный усилитель, но звук от него довольно тихий. Так же есть возможность вывести часть управления на внешние кнопки миную контроллер, но я не увидел в этом необходимости.
Подключение питания к 5 вольтам.
Подключение к ардуино по 3-м (!) проводам. RX , TX и BUSY. Два первых провода передают и получают данные к/от ардуино по программному serual- порту, такие как : запуск и остановка треков, изменение громкости, получение кол-ва треков на мини-сд-карте. Эти провода надо подключать через резистор номиналом 1-2 килоОма. Третий провод предназначен для получения информации о состоянии плеера: идет воспроизведение или нет. В принципе такую информацию можно получить через команду по Serial, но это может подвешивать работу всего устройства, в то время как чтение порта практически ни на что не влияет.
Структура карты:
На карте должно быть 2 подкаталога "01" и "02". Каталог "01" содержит музыкальные треки для фоновой мелодии, а "02" содержит тосты для воспроизведения налива. В принципе названия могут быть любыми, главное что бы каталог с музыкальными фрагментами для фоновой мелодии были в начале по алфавиту. При изменении кол-ва музыкальных треков на карте при включении наливатора будет запущена конфигурационная процедура настройки, в которой следует указать кол-во мелодий для фона, все остальные скетч будет считать тостами.

ВАЖНО! Папка с музыкой должна копироваться или создаваться на карте 1-ой! Именно треки в 1-ой созданной папке будут считаться музыкой.
В отдельном посте опубликую ссылки на свои мелодии и тосты, с текстовыми описаниями. Попробуем сделать обмен тостами.
Библиотека для плеера

Подсветка мест для налива
Для подсветки мест используется адресная светодиодная лента и библиотека FastLED
LED.png
Можно использовать как 1 отдельный светодиод на место, так и вот такие кольца, а так же огрызки ленты по несколько светодиодов.
Ограничение одно - на всех местах для налива должно быть одинаковое число светодиодов.
Файл silver_naliv_20.ino
Общее число светодиодов рассчитывается как число светодиодов на 1 место помноженное на число мест.
В данном примере используется по 1-му светодиоду на место.
C++:
#define NUM_LEDS  LEDs_per_Drink*max_DrinkCount // Кол-во диодов (количество светодиодов на рюмку умножить на число рюмок, математика, 3-ий класс
Строки 42-45
C++:
#define max_DrinkCount 5               // Максимальное кол-во рюмок, при подключении на аналоговые пины максимум 6 рюмок при нано
#define LEDs_per_Drink 1               // Число светидиодов на рюмку, считается что под рюмкой такое число лампочек
Номер 1-го светодиода для каждого мест настраивается отдельно в файле drink_place.ino
C++:
// номер 1-го светодиода для каждой рюмки.  Могут быть не по порядку
  drinks_array[0].N_LED = 32768; // это место парковки и оно не подсвечивается !
  drinks_array[1].N_LED = 0;
  drinks_array[2].N_LED = 1;
  drinks_array[3].N_LED = 2;
  drinks_array[4].N_LED = 3;
  drinks_array[5].N_LED = 4;
В данном примере используется по 12 светодиодов на место.
C++:
#define max_DrinkCount 5               // Максимальное кол-во рюмок, при подключении на аналоговые пины максимум 6 рюмок при нано
#define LEDs_per_Drink 12               // Число светидиодов на рюмку, считается что под рюмкой такое число лампочек
C++:
// номер 1-го светодиода для каждой рюмки.  Могут быть не по порядку
  drinks_array[0].N_LED = 32768;
  drinks_array[1].N_LED = 0;
  drinks_array[2].N_LED = 12;
  drinks_array[3].N_LED = 24;
  drinks_array[4].N_LED = 36;
  drinks_array[5].N_LED = 48;

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

Дополнительные библиотеки
DIO2 - для более быстрого доступа к цифровым пинам.
EEPROMex - расширенное управление чтением и записью в EEPROM

Подключение шагового двигателя.
Для подключения шагового двигателя я предлагаю такой вариант:
входы 6 7 8 9 подключаются к in1 in2 in3 in4 платы с микросхемой ULN2003A.
на моторе.png
stepper.jpg
Собирается все просто. К микро кнопке (такая же как стоит на ресете ардуино нано) подпаиваются 2 провода, кнопка вставляется в 1-ую деталь, вторая подпирает ее и изолирует от мотора. Носик надевается на вал двигателя. Его надо надежно закрепить так, что бы кнопка зажималась при вращении и он не мешал движению. Сверху носика еще будет достаточно места, что бы на валу закрепить что то.
на мотор.png крышка.png носик.png
Ссылка на STL
Рыская на просторах Али нашел такое описание данного двигателя. шаг получается 5,625/64, т.е. 4096 шагов на оборот. В скетче изначально использовалось почему то 4076 шагов на оборот (не мое, брал из скетча). Число надо изменить на верное! Думаю сделать это каждый может самостоятельно.
step.png

Варианты корпусов:

Описание сборки мной на макетке, спустя некоторое время
 
Изменено:

Комментарии

Bladeslider

✩✩✩✩✩✩✩
11 Сен 2020
6
0
Старик Похабыч, не думали дополнить ваш превосходный наливатор второй помпой и и вторым краником, чтобы была возможность разливать не только один напиток, а например наливать виски с колой?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Сейчас вспомнил.. я тоже подключал плеер к усилителю и тоже был треск.. Но он как то сам пропал и очень быстро. Повторно его вызвать не вышло. Подключал стерео. т.е. по 3-м проводам, но на выход для наушников
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Настройки сохраняются если выйти из меню длинным нажатием, когда курсор не на промывке. Если выход по таймауту, то изменения до выключения питания.
Нет все зависает
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Вся музыка обрабатывается вот в этой функции MusicTick() из файла tost.ino
Надо попробовать посмотреть в каком месте происходит зависание. Музыка должна играть сразу как ставится галка в настройках.
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Играют тосты. Но выйти не могу и по тайм-ауту не выходит, потому что висит. А если питание выключить то и Настройки не сохраняются. А в остальном все работает.
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Как только включаю тосты и музыку сразу зависает ардуино, энкодер не реагирует экран горит, до налива дело не доходит. Выключаю питание затем включаю, захожу в Настройки тосты и Музыка выключены.

Так.. А из режима налива 1-го по таймауту выходит ? Экран по таймауту гаснет?
Если без плеера то да
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Попробую. Но не должно. Повышай-ка выдаёт до 6 А. Да и вольтметр показывает ровно 5 в.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Что то же происходит. Еще один тест предлагаю для чистоты. С другой стороны от подключения колонок так же есть пин земли. Он симметричен относительно 1-го пина земли, если ось симметрии между рядами пинов. Так вот если взять провод и замкнуть коротким касанием землю и любой из ее соседних пинов (не там где колонки!) то плеер воспримет это как кнопку либо плей некст, либо плей прев. И должна пойти музыка. Проверить можно в любом месте
 

LVit

★✩✩✩✩✩✩
2 Окт 2020
18
10
@Старик Похабыч, Такой вопрос, можно ли сделать так , чтобы фоновая музыка играла только во время налива?В остальное время молчок. Т.е. , пошёл разлив, играет фон. Разлив окончился, тост. Как то утомляет постоянный фон
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Наверное можно :) Вообще если уметь. то мало чего невозможного..
Я у себя менять не буду, но попробую подсказать без тестов.
Есть такой файл pump.ino, вот его содержимое:
C++:
void Motors_tick2()
{

  // управление помпой, если изменилось состояние
  static bool old_pump_state = false;
  if (Pump_clear != old_pump_state)
  {
    if (Pump_clear) pump_enable();
    else pump_disable();
    old_pump_state = Pump_clear;
  }

  {
    switch (p_State)
    {
      case ps_idle:
        Curent_Step = ws_Step1;
        break;
      case ps_auto_naliv:
        Auto_tick();
        break;
      case ps_manual_naliv:
        Manual_tick();
        break;
      case ps_game_naliv:
        Game_tick();
        break;
    }
  }
};

void pump_enable() {
  digitalWrite2(PIN_PUMP, 1);
}

void pump_disable() {
  digitalWrite2(PIN_PUMP, 0);
}
Он как раз вызывает разные режимы налива, думаю понятно где какой

И есть файл tost.ino
C++:
bool EnableVolContr = true;
bool isTost = false;

void SayTost()
{ 
  if (!MP3_avail) return; // выход если не иницирован плейер   
  if (!say_tost) return; // если тосты не говорить, то выход 
  if ((digitalRead2(BUSY_MP3_PIN) == 0)&&isTost) return; // произносится длинный тост.
  EnableVolContr = false;
  isTost=true;
 
  static uint16_t OldTost = 0;
  static uint16_t NewTost;
  do
    NewTost = random(MAX_FON_SOUND + 1, MAX_SOUND + 1);
  while (NewTost == OldTost);
  OldTost = NewTost;
  myDFPlayer.stop();
  delay(100);
  myDFPlayer.volume(MP3_Tost_Vol);
  delay(100);
  myDFPlayer.play(NewTost);
  delay(100);
}

void PlayFon()
{
  if (!MP3_avail) return; // выход если не иницирован плейер
 
  static uint16_t OldFon = 0;
  static uint16_t NewFon;
  do
    NewFon = random(1, MAX_FON_SOUND + 1);
  while (NewFon == OldFon);
  OldFon = NewFon;
  myDFPlayer.volume(MP3_Fon_Vol);
  delay(200);
  myDFPlayer.play(NewFon);
  delay(200);
}

void MusicTick()
{
  if (!MP3_avail) return; // выход если не иницирован плейер
 
  static uint32_t LastCheck = 0;
  if (play_fon)
  {
    if ((millis() - LastCheck) > 1000)
    {
      if (EnableVolContr)  myDFPlayer.volume(MP3_Fon_Vol);
      if (digitalRead2(BUSY_MP3_PIN) == 1)
      {
        isTost=false;
        PlayFon();
        EnableVolContr = true;
      }
      LastCheck = millis();
    }
  }
  else
  {
    if (digitalRead2(BUSY_MP3_PIN) == 0) // работаетм!
    {
      if (EnableVolContr)  myDFPlayer.stop();
    }
    else
    {
      EnableVolContr = true;
    }
  }
}
В нем интересна процедура MusicTick(), которая как раз отвечает за проигрывание музыки.
1 строка - проверка, что плеер доступен, если нет - то выход.
Далее уже не так интересно, там проверки на вкл/выкл, на тосты и прочее. Туда лезть не надо.
Так вот если после 1-ой строки вставить проверку на режим работы то можно такой очень легко провернуть буквально одной строкой. Во всяком случае я так думаю.

Надо проанализировать текущее состояние наливатора и если в это время не надо играть , то просто выйти из функции
Анализировать надо p_State, вот ее возможные состояния:
enum process_state : uint8_t {ps_idle, ps_auto_naliv, ps_manual_naliv, ps_game_naliv, ps_settings}; //
 
  • Лойс +1
Реакции: LVit

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
По поводу шумов. Подключил мощный усилитель,типа такого. К выходу динамиков, был треск. Убрал установив громкость на максимум, тогда паразитных шумов не стало слышно совсем.
1606568885234.png
Видео со звуком на макетке. Усилитель запитан отдельно от 10в
 
Изменено:

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
А такой энкодер с эффектом памяти (Trema-модуль v2.0) подойдет? В отличии от обычных энкодеров, данный модуль сам определяет факт и направление каждого шага поворота вала. Для чтения данных с модуля используются обычные функции digitalRead без использования библиотек и таймеров.
 
  • Лойс +1
Реакции: Старик Похабыч

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Не пробовал, но все возможно. Надо только убрать штатную библиотеку и все функции обращения к энкодеру подменить. А так.. какая разница ? хоть кнопками нажимай )
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
@Anatolyj, Готовы попробовать с "памятливым" энкодером версию ? Я сейчас допилию замену библиотеки , а то что то двойные повороты считает и скину инструкцию

@Bladeslider, Ближайшее время вряд ли. Хотя задумка есть , я уже говорил. На линейном приводе, с мегой и тачскрином. Но пока больше в голове.

Инструкция!
В приложении 2 файла, inc - тестовая прошивка для проверки подключения тремошилда с экнодером 2.0
Второй файл это подправленная библиотека encMinim.h для работы с этим самым энкодером.

Что надо поменять в наливаторе:

Файл silver_naliv_20.ino
1) Строка 20. #include "encMinim.h" заменить на #include "t_encMinim.h"
2) Строка 28. encMinim enc(pin_A, pin_B, pin_SW, ENCODER_REV, ENCODER_TYPE); заменить на encMinim enc(pin_A, pin_B, pin_SW);
3) Строка 291. if (!digitalRead(pin_SW)) заменить на if (digitalRead(pin_SW))

Файл eeprom_proc.ino
4) Строки 123 и 206 в while (!digitalRead(pin_SW)) {}; убрать "!"

Файл enc_proc.ino
5) Строки 328 и 329 сделать так:
if ((digitalRead2(pin_SW) == 0) && (!Pump_clear)) return false;
if ((digitalRead2(pin_SW) == 0) && (Pump_clear))


При этом pin_A это будет R, pin_B это T , а pin_SW это соотв К. V и G энкодера это соотв +5 и GND

Тестируйте! И спасибо за идею, а то что то я его не использовал, руки не доходили.
 

Вложения

Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
У меня тянул 12 светодиодов. не на максимуме конечно. Сеову мелкую , плеер. При этом плеер лучше прицепить к +5 волтьтам. Сама эта шняга питалась от 9в 3а бп. Ну и сейчас на ней собрано все. Единственное усилитель питал отдельно от 8 вольт
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Посмотрел свой усилитель лопает 1,2 А и причём моно но он на 5 w. Хочу его убрать. Динамик всего на 3 w и смысла в усилителе думаю нет. Только лишние амперы.
 

Anatolyj

★✩✩✩✩✩✩
30 Янв 2020
134
15
Нет. Во вторник только посылка придёт. Пока только пришёл питальник для макетной платы. Наконец то можно будет проверять все перед сборкой. А то соберёшь и где-то косяк и все перепаивать приходиться.
Как этот энкодер получу сразу буду пробовать.
Пока за это время хочу плату сделать, чтобы было проще собирать. Как то раньше делал платы методом ЛУТ , но это было лет 10 назад. Вот хочу вспомнить былое.