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

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

atom23rus пишет:

Парни, а подскажите как откалибровать насос?

Секундомер есть в каждом сматрфоне, подоединяешь насос, через кнопку подаешь напряжение строго от внешнего источника  которым будеш его питать, делаешь 10-20 замеров, высчитываешь среднее арифметическое. Насос 385 при питании 5В потребляет 150мА, 50 мЛ наливает в среднем за 5,5 сек.(5550 мсек)

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

stpavel пишет:

У меня к сожалению нет mp3 модуля, что бы проверить. Нужно что бы наливатор говорил тосты после каждого налива ? Тогда засовывать надо в процедуру Tost()

Что бы писал "Ну начали" перед наливом , можно засунуть в процедуру oled_naliv.

"Ну начали" надо програть всего один раз, после включения и подсоединения ёмкости, можно даже на дисплей не выводить.

atom23rus
Offline
Зарегистрирован: 06.08.2019

в этом то и прикол.в магазине был только 360 и на 12 вольт.буду питать от 8в.я о том где в скетче прописывать калибровку.

 

 

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Forthomo пишет:

stpavel пишет:

У меня к сожалению нет mp3 модуля, что бы проверить. Нужно что бы наливатор говорил тосты после каждого налива ? Тогда засовывать надо в процедуру Tost()

Что бы писал "Ну начали" перед наливом , можно засунуть в процедуру oled_naliv.

"Ну начали" надо програть всего один раз, после включения и подсоединения ёмкости, можно даже на дисплей не выводить.

Ну если один раз при включении, можно засунуть в setup

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

stpavel пишет:

Ну если один раз при включении, можно засунуть в setup

#include <OLED_I2C.h>
#include <Servo.h>
#include "Adafruit_NeoPixel.h"
#include <SoftwareSerial.h>//добавляем библиотеки
#include <DFPlayer_Mini_Mp3.h>//добавляем библиотеку МП3 плейера

// при необходимости создаем програмный порт для управдения МП3 плейером, если вывод в монитор TX(D0) RX(D1) необходим
//SoftwareSerial mySoftwareSerial(10, 11); // RX, TX  обозначаем програмный порт как mySoftwareSerial
//плейер подключаем D10 D11

OLED  myOLED(SDA, SCL, 8); //Подключение экрана А4, А5
extern uint8_t MegaNumbers[];
extern uint8_t RusFont[];
extern uint8_t SmallFont[];
unsigned long currentTime;
unsigned long loopTime;
unsigned long ledTime;
// Переменные для энкодера -----------
const int pin_A = 2;       // Подключение вывода A (CLK) энкодера
const int pin_B = 3;       // Подключение вывода B (DT) энкодера
const int pin_SW = 4;       // Подключение вывода кнопки (SW) энкодера
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev = 0;
unsigned char encoder_sw_prew = 1;
//Массив , обозначаем подключенные оптопары по выводам . Оптопары подключены, A0,A1,A2,A3,A6
const byte  Optics[] = {0, 1, 2, 3, 6};
//Серво
const int PIN_SERVO = 9;
Servo servo;
//Позиция каждой рюмки 
const byte Rumka_pos[] = {0,40,75,105,140};
//-------------------------
byte  Menu = 0;
byte MenuFlag = 0; // Здесь храниться уровень меню. 0 находимся в  Главном меню. 1 Вошли в меню Авто, 2 вошли в  Ручное управление
byte  Drink = 25; // По умолчанию в рюмку наливаем  20 мл.
const byte  max_Drink = 50; // Максимум в рюмку - 50 мл.
byte  DrinkCount = 1; //По умолчанию, для ручного режима - 1 рюмка
const byte  max_DrinkCount = 5; //Максимальное кол-во рюмок - 5
// Насосик
const byte PIN_PUMP = 12;
// Светодиоды
const int PIN_LED = 5;// Сюда подключаются светодиоды
const int LED_COUNT = max_DrinkCount;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN_LED, NEO_GRB + NEO_KHZ800);

//-------

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

void pump_disable() {
  digitalWrite(PIN_PUMP, 0);
}

void pump_timer(byte Drink) {
  digitalWrite(PIN_PUMP, 1);
  delay(map(Drink, 2, 50, 300, 4000));
  digitalWrite(PIN_PUMP, 0);
}

void oled_menu(int Menu) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("Y F K B D F N J H"), CENTER, 0);//Н А Л И В А Т О Р
  myOLED.print(F("F D N J"), CENTER, 15);//А В Т О
  myOLED.print(F("H E X Y J Q "), CENTER, 30);//Р У Ч Н О Й 
  myOLED.print(F("G H J V S D R F"), CENTER, 45);//П Р О М Ы В К А
  myOLED.setFont(SmallFont);
  myOLED.print(F(">"), LEFT, (Menu * 15) + 15);
  myOLED.print(F("<"), RIGHT, (Menu * 15) + 15);
  myOLED.update();

}
//  выводит строчку по чуть чуть, в самый раз и тд. Передается номер строки, на которой выводить сообщение
void DrinkInfo(byte pos) {
  if (Drink < 15) {
    myOLED.print(F("YB J XTV"), CENTER, pos);//НИ О ЧЕМ
  } else if (Drink < 28) {
    myOLED.print(F("GJ XENM - XENM"), CENTER, pos);//ПО ЧУТЬ - ЧУТЬ
  } else if (Drink < 38) {
    myOLED.print(F("D CFVSQ HFP"), CENTER, pos);//В САМЫЙ РАЗ
  } else if (Drink < 48) {
    myOLED.print(F("GJ GJKYJQ"), CENTER, pos);//ПО ПОЛНОЙ
  } else {
    myOLED.print(F("LJ RHFTD"), CENTER, pos);//ДО КРАЕВ
  }

}

	void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("Ye?"), CENTER, 20); //Ну,
  // Рандом - 1
  switch (random(18)) {
    case 0:
      myOLED.print(F("pf dcnhtxe!"), CENTER, 40); //за встречу!
      mp3_play (2);  // Проигрываем "mp3/0002.mp3"
	  delay(100);
	  mp3_stop();
	  break;
    case 1:
      myOLED.print(F("pf rhfcjne!"), CENTER, 40); //за красоту!
      mp3_play (3);  // Проигрываем "mp3/0003.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 2:
      myOLED.print(F("pf lhe;,e!"), CENTER, 40); //за дружбу!
      mp3_play (4);  // Проигрываем "mp3/0004.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 4:
      myOLED.print(F("pf ,hfncndj!"), CENTER, 40); //за братство!
      mp3_play (5);  // Проигрываем "mp3/0005.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 5:
      myOLED.print(F("pf"), CENTER, 38); //за
	  myOLED.print(F("cghfdtlkbdjcnm!"), CENTER, 55); //справедливость!
      mp3_play (6);  // Проигрываем "mp3/0006.mp3"
	  delay(100);
	  mp3_stop();
	  break;
    case 6:
      myOLED.print(F("pf hs,fkre!"), CENTER, 40); //за рыбалку!
      mp3_play (7);  // Проигрываем "mp3/0007.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 7:
      myOLED.print(F("pf bcreccndj!"), CENTER, 40); //за искусство!
      mp3_play (8);  // Проигрываем "mp3/0008.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 8:
      myOLED.print(F("pf hfpev!"), CENTER, 40); //за разум!
      mp3_play (9);  // Проигрываем "mp3/0009.mp3"
	  delay(100);
	  mp3_stop();
	  break; 
	case 9:
      myOLED.print(F("pf bcnbyys["), CENTER, 38); //за истинных
	  myOLED.print(F(";tyoby!"), CENTER, 55); //женщин!
      mp3_play (10);  // Проигрываем "mp3/0010.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 10:
      myOLED.print(F("pf gjybvfybt!"), CENTER, 40); //за понимание!
      mp3_play (11);  // Проигрываем "mp3/0011.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 11:
      myOLED.print(F("pf tlbytybt!"), CENTER, 40); //за единение!
      mp3_play (13);  // Проигрываем "mp3/0013.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 12:
      myOLED.print(F("pf Gj,tle!"), CENTER, 40); //за Победу!
      mp3_play (16);  // Проигрываем "mp3/0016.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 13:
      myOLED.print(F("pf Hjlbye!"), CENTER, 40); //за Родину!
      mp3_play (20);  // Проигрываем "mp3/0020.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 14:
      myOLED.print(F("xnj, ujkjdf"), CENTER, 38); //чтоб голова
	  myOLED.print(F("yt nhtofkf!"), CENTER, 55); //не трещала!
      mp3_play (17);  // Проигрываем "mp3/0017.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 15:
      myOLED.print(F("pf cjkblyjt"), CENTER, 38); //за солидное
	  myOLED.print(F("ve;crjt vjkxfybt"), CENTER, 55); //мужское молчание
      mp3_play (12);  // Проигрываем "mp3/0012.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 16:
      myOLED.print(F("xnj, vjhobkj"), CENTER, 38); //чтоб морщило
	  myOLED.print(F("vtymit!"), CENTER, 55); //меньше!
      mp3_play (18);  // Проигрываем "mp3/0018.mp3"
	  delay(100);
	  mp3_stop();
	  break;
	case 17:
      myOLED.print(F("xnj, d cnjhjye"), CENTER, 38); //чтоб в сторону
	  myOLED.print(F("yt dbkmyekj!"), CENTER, 55); //не вильнуло!
      mp3_play (19);  // Проигрываем "mp3/0019.mp3"
	  delay(100);
	  mp3_stop();
	  break;      
  }
  myOLED.update();

}
/*
void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("DSGMTV"), CENTER, 20); //Выпьем
  // Рандом - 1
  switch (random(11)) {
    case 0:
      myOLED.print(F("PF LHEPTQ!"), CENTER, 40); //За друзей
      break;
    case 1:
      myOLED.print(F("PF VBKS{ LFV!"), CENTER, 40); //За милых дам
      break;
    case 2:
      myOLED.print(F("PF PLJHJDMT!"), CENTER, 40); //За здоровье
      break;
    case 3:
      myOLED.print(F("PF ELFXE!"), CENTER, 40); //За удачу
      break;
    case 4:
      myOLED.print(F("PF VBH DJ DCTV VBHT!"), CENTER, 40); //За мир во всем мире
      break;
    case 5:
      myOLED.print(F("PF NT{ RNJ D VJHT!"), CENTER, 40); //За тех кто в море
      break;
    case 6:
      myOLED.print(F("PF K><JDM !"), CENTER, 40); //За любовь !
      break;
    case 7:
      myOLED.print(F("PF RHFCJNE !"), CENTER, 40); //За красоту !
      break;
    case 8:
      myOLED.print(F("PF DTPTYBT !"), CENTER, 40); //За везение !
      break;
    case 9:
      myOLED.print(F("PF HJLBYE !"), CENTER, 40); //За родину !
      break;
    case 10:
      myOLED.print(F("PF YFC C DFVB"), CENTER, 38); //За нас с вами
      myOLED.print(F("B {HTY C YBVB !"), CENTER, 55); //И хрен с ними
      break;

  }
  myOLED.update();
}
*/

// Меню Авто режим
void oled_auto(int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("F D N J"), CENTER, 0);
  myOLED.print(F("VK   "), RIGHT, 27);
  DrinkInfo(57);
  //  myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(Drink), CENTER, 13);
  myOLED.update();
}

// Меню Ручной режим
void oled_manual(int DrinkCount, int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("H E X Y J Q"), CENTER, 0);
  DrinkInfo(57);
  // myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.print(F("H>V"), 24, 27);
  myOLED.print(F("VK "), RIGHT, 27);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(DrinkCount), LEFT, 13);
  myOLED.print(String(Drink), (Drink < 10) ? 80 : 57, 13);
  myOLED.update();
}


void oled_naliv(int MenuFlag) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);

  myOLED.print(F("Y F K B D F > "), CENTER, 27);
  DrinkInfo(47);
  myOLED.update();
}

void oled_nalito(int MenuFlag, int Nalito) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);
  myOLED.print(F("Y F K B N J"), CENTER, 20);
  if (Nalito == 1) {
    myOLED.print(F("H > V R F"), CENTER, 55);
  } else if (Nalito <= 4 ) {
    myOLED.print(F("H > V R B"), CENTER, 55);
  } else {
    myOLED.print(F("H > V J R"), CENTER, 55);
  }

  myOLED.setFont(SmallFont);
  myOLED.print(String(Nalito), CENTER, 36);
  myOLED.update();
}

void ServoNaliv(byte rumka) {
  servo.attach(PIN_SERVO);
  for (int pos = servo.read(); pos <= Rumka_pos[rumka]; pos += 1) { 
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(10); // ждем 15 миллисекунд, пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();


}

void ServoParking () {
  //Serial.println(servo.read());
  servo.attach(PIN_SERVO);
  for (int pos = servo.read();  pos >= 0; pos -= 1) {
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(10); // ждем 15 миллисекунд, пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();
}

void CvetoMuzik() {
  for (int i = 0; i <= 7; i++) {
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(255, 0, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 255, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 0, 255));
      strip.show();
      delay(30);
    }
  }
}

void setup()  {
  //Serial.begin(9600);
  //  servo.attach(PIN_SERVO);
  pinMode(pin_SW, INPUT); // устанавливаем pin pin_SW как вход
  digitalWrite(pin_SW, HIGH); // Поддяжка вывода к 1
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  pinMode(PIN_PUMP, OUTPUT);
  digitalWrite(PIN_PUMP, 0);
  currentTime = millis();
  loopTime = currentTime;
  //---------------
	Serial.begin(9600);//
	//устанавливаем Serial порт МП3 плейера если вывод в монитор TX(D0) и RX(D1)не нужен 
	mp3_set_serial (Serial);//инициализируем Serial порт МП3 плейера
	/*	
	mySoftwareSerial.begin(9600);//инициализируем програмный Serial порт 
	mp3_set_serial (mySoftwareSerial);// указываем програмный порт для МП3 плейера (см. 8)
	//инициализируем Serial с скоростью 115200, если вывод в монитор  TX(D0) RX(D1) необходим 
	Serial.begin(115200);
	*/	
	delay (100);//Между двумя командами необходимо делать задержку 100 миллисекунд, в противном случае некоторые команды могут работать не стабильно.
	mp3_set_volume (25);// устанвливаем громкость 25
	delay (100);
  mp3_play (1); // Проигрываем "mp3/0001.mp3"(0001_get started!.mp3)
  delay (100);
  
	//------------------
  //   Volume=EEPROM.read(0);
  myOLED.begin();
  // выводим привествие после включения перед наливом
  myOLED.clrScr();  
  myOLED.setFont(RusFont);
  myOLED.print(F("Ye? yfxfkb!"), CENTER, 50);// Ну, начали!
  myOLED.update(); 
  //
  oled_menu(0);
  strip.begin();
  for (int i = 0; i < 5; i++) {
    pinMode(Optics[i], INPUT);
  }
  ServoParking();

}
/*//---------------
// выводим привествие после включения перед наливом
  myOLED.clrScr();  
  myOLED.setFont(RusFont);
	myOLED.print(F("Ye? yfxfkb!"), CENTER, 50);// Ну, начали!
	myOLED.update(); 
// и озвучиваем

	mp3_set_volume (28);// устанвливаем громкость 28 (0_30)
	delay (100);
	mp3_play (1); // Проигрываем "mp3/0001.mp3"(0001_get started!.mp3)
	mp3_stop (1); // остановить воспроизведение
	mp3_set_volume (20);// устанвливаем громкость 20 (0_30)
//	delay (2000); //ждем 2 секунды
//----------------------------
*/  
void loop()  {
  currentTime = millis();
  if (currentTime >= (loopTime + 5)) { // проверяем каждые 5мс

    //     int  val = analogRead(0);     // считываем значение
    //  Serial.println(val);
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера
    if ((!encoder_A) && (encoder_A_prev)) {  // если состояние изменилось с положительного к нулю

      //Вращение влево
      if (encoder_B) {
        if (MenuFlag == 0) {
          (Menu <= 0 ) ? Menu = 2 : Menu--; // Перемещение курсора по главному меню назад
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink <= 2 ) ? Drink = max_Drink : Drink--; // Уменьшаем кол-во милилитров в рюмку
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (DrinkCount >= max_DrinkCount ) ? DrinkCount = 1 : DrinkCount++; // Влево увечичиваем рюмки для ручного режима
          oled_manual(DrinkCount, Drink);
        }
        //Вращение вправо
      } else {
        if (MenuFlag == 0) {
          (Menu >= 2 ) ? Menu = 0 : Menu++; // Перемещение курсора по главному меню вперед.
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink >= max_Drink ) ? Drink = 2 : Drink++;
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (Drink >= max_Drink ) ? Drink = 2 : Drink++;
          oled_manual(DrinkCount, Drink);
        }
      }

    }

    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла

    int encoder_sw = digitalRead(pin_SW);
    if  (encoder_sw == 0 && encoder_sw != encoder_sw_prew)  { // Нажата кнопка

      int pause_sw = 0;
      boolean promivka = false;
      while (digitalRead(pin_SW) == 0) { // Держим кнопку. Считаем сколько времени прошло...
        delay(100);
        pause_sw++;
        if (pause_sw > 20 && Menu != 2 ) break;

        if (pause_sw > 20 && Menu == 2 && promivka == false) { // Если пункт меню промывка и держим кнопку больше 2 секунд.
          promivka = true;
          pump_enable(); // Включаем насос
          myOLED.clrScr();
          myOLED.setFont(RusFont);
          myOLED.print(F("G H J V S D R F"), CENTER, 15);//П Р О М Ы В К А
          myOLED.print(F(". . ."), CENTER, 45);
          myOLED.update();
        }
      }

      //После отпускания кнопки , обрабатываем
      if (promivka == true) { //Отпустили кнопку. Если включена промывка, выключаем насос и возвращаемся в главное меню
        promivka = false;
        pump_disable() ; //Выключаем насос
        oled_menu(2);

      } else {
        //Обработка всех нажатий кнопки
        if (Menu == 0 && MenuFlag == 0 &&  pause_sw < 10) { //Нажатие кнопки меню авто
          MenuFlag = 1;
          oled_auto(Drink);
        } else if (MenuFlag == 1 && pause_sw > 20) { //Выход из меню авто в главное
          MenuFlag = 0;
          oled_menu(0);
        } else if (MenuFlag == 1 ) { //Начинается автоматический разлив
          Serial.println("Начало автоматического разлива");
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          byte drink_count = 0;
          for (int y = 0; y < max_DrinkCount; y++) {
            if (analogRead(Optics[y]) > 1000 ) {
              strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
              strip.show();
              ServoNaliv(y); // Перемещяемся к рюмке
              pump_timer(Drink); // Налив.
              strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
              strip.show();
              drink_count++;
            }
          }
          if (drink_count > 0) {
            oled_nalito(MenuFlag, drink_count );
            ServoParking();
            delay(1000);
            Tost();
            CvetoMuzik();
            oled_auto(Drink);
          } else {
            myOLED.clrScr();
            myOLED.setFont(RusFont);
            myOLED.print(F("YTN H>VJR !"), CENTER, 25);//НЕТ РЮМОК !
            myOLED.update();
            delay(2000);
            oled_auto(Drink);

          }
        } else if (Menu == 1 && MenuFlag == 0 &&  pause_sw < 10) { // Нажатие меню ручное
          MenuFlag = 2;
          oled_manual(DrinkCount, Drink);
        } else if (MenuFlag == 2 && pause_sw > 20) { //Выход из меню ручное в главное
          MenuFlag = 0;
          oled_menu(1);
        } else if (MenuFlag == 2 ) { //Начинается ручной разлив
          //  Serial.println("Начало ручного разлива " + String(DrinkCount));
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          for (int y = 0; y < DrinkCount; y++) {
            strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
            strip.show();
            ServoNaliv(y); // Перемещяемся к рюмке
            pump_timer(Drink); // Налив.
            strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
            strip.show();
          }
          oled_nalito(MenuFlag, DrinkCount );
          ServoParking();
          Tost();
          CvetoMuzik();
          oled_manual(DrinkCount, Drink);
        }
      }
    }

    if (currentTime >= (ledTime + 300)) {
      //Опрашиваем оптопары ... Если рюмка поставлена , светодиод светится синим, нет ничего - не светится
      for (int i = 0; i < max_DrinkCount; i++) {
        
        int val = analogRead(Optics[i]);     // считываем значение
        Serial.println(val);
        if (val > 1000) {
          strip.setPixelColor(i, strip.Color(0, 0, 255));
        } else {
          strip.setPixelColor(i, strip.Color(0, 0, 0));
        }
    //    delay(20);

      }
      strip.show();
      ledTime = currentTime;
    }
    encoder_sw_prew = encoder_sw;
    loopTime = currentTime;

  }
}

Скетч использует 16430 байт (53%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1419 байт (69%) динамической памяти, оставляя 629 байт для локальных переменных. Максимум: 2048 байт.

Может кто в железе проверит?

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

atom23rus пишет:

в этом то и прикол.в магазине был только 360 и на 12 вольт.буду питать от 8в.я о том где в скетче прописывать калибровку.

 

 

Не видел такого в скетче

stpavel
Онлайн
Зарегистрирован: 09.10.2018

atom23rus пишет:

в этом то и прикол.в магазине был только 360 и на 12 вольт.буду питать от 8в.я о том где в скетче прописывать калибровку.

Если речь о моем скетче то калибровка в процедуре  pump_timer

	  delay(map(Drink, 2, 50, 300, 4000));

Здесь задается соотношение милилитров и задержки.

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

Если устраивает диапазон от 2 до 50 мл, меняй значения 300 ( подразумевает 2 мл. ) и 4000 ( 50 мл) , остальное расчитается само .

 

 

atom23rus
Offline
Зарегистрирован: 06.08.2019

вот и я не увидел.

 

atom23rus
Offline
Зарегистрирован: 06.08.2019

да,про твой.спс. Задержка в милисекундах?

stpavel
Онлайн
Зарегистрирован: 09.10.2018

atom23rus пишет:

да,про твой.спс. Задержка в милисекундах?

конечно.

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019
void pump_timer(byte Drink) {
  digitalWrite(PIN_PUMP, 1);
  delay(map(Drink, 10, 50, 1100, 5550));
  digitalWrite(PIN_PUMP, 0);
}

У меня так 10 мЛ - 1,1сек (1100 милисекунд), 50 мл- 5500 милисекунд.

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

atom23rus пишет:

в этом то и прикол.в магазине был только 360 и на 12 вольт.буду питать от 8в.я о том где в скетче прописывать калибровку.

 

 

Вот тут насос заказывал

https://amperkot.ru/msk/catalog/miniatyurnyiy_membrannyiy_nasos_385_612v-24139016.html

atom23rus
Offline
Зарегистрирован: 06.08.2019

да я бы и с китая заказал,просто мне срочно нужен был

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

stpavel, какие датчики используешь что у тебя на входах порог  val > 1000?
Уменя вот так:
A0    70,8    405,8
A1    51       324,4
A2    83       528,8
A3    131    652
A6    281    933,2
 Итого: val > 300

схема датчика на второй странице
 

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Forthomo пишет:

stpavel, какие датчики используешь что у тебя на входах порог  val > 1000?
Уменя вот так:
A0    70,8    405,8
A1    51       324,4
A2    83       528,8
A3    131    652
A6    281    933,2
 Итого: val > 300

схема датчика на второй странице
 

Использую вот такие датчики https://ru.aliexpress.com/item/4000036567119.html?spm=a2g0s.9042311.0.0.528c33ed9tRBaQ

На каждом установлен инвертирующий триггер Шмидта 74HC14D, который поидее должен хорошо подавлять дребезг.  У меня нет обычных  TCRT5000 что бы проверить как будет работать без этой микросхемы, но думаю с ней однозначно будет лучше. 

Чуть поменял код, вынес настройки для калибровки насосика в самый верх. 

//----- Минимальные и максимальные значения наполняемой жидкости и задержки для наполнения. 
const byte  min_Drink = 2; // Минимум в рюмку - 2 мл.
const byte  max_Drink = 50; // Максимум в рюмку - 50 мл.
// Калибровка работы насосика. Значения для налива min_Drink и max_Drink соотвественно 
const unsigned int min_Drink_delay = 300; 
const unsigned int max_Drink_delay = 4000;
//--------

 

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

// Значения порога срабатывания датчика для каждой рюмки
const unsigned int Optics_porog[] = {1000,1000,1000,1000,1000};

 

#include <OLED_I2C.h>
#include <Servo.h>
#include "Adafruit_NeoPixel.h"

OLED  myOLED(SDA, SCL, 8); //Подключение экрана А4, А5
extern uint8_t MegaNumbers[];
extern uint8_t RusFont[];
extern uint8_t SmallFont[];
unsigned long currentTime;
unsigned long loopTime;
unsigned long ledTime;
// Переменные для энкодера -----------
const int pin_A = 2;       // Подключение вывода A (CLK) энкодера
const int pin_B = 3;       // Подключение вывода B (DT) энкодера
const int pin_SW = 4;       // Подключение вывода кнопки (SW) энкодера
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev = 0;
unsigned char encoder_sw_prew = 1;
//Массив , обозначаем подключенные оптопары по выводам . Оптопары подключены, A0,A1,A2,A3,A6
const byte  Optics[] = {0, 1, 2, 3, 6};
// Значения порога срабатывания датчика для каждой рюмки
const unsigned int Optics_porog[] = {1000,1000,1000,1000,1000};
//Серво
const int PIN_SERVO = 9;
Servo servo;
//Позиция каждой рюмки 
const byte Rumka_pos[] = {0,40,75,105,140};
//-------------------------
byte  Menu = 0;
byte MenuFlag = 0; // Здесь храниться уровень меню. 0 находимся в  Главном меню. 1 Вошли в меню Авто, 2 вошли в  Ручное управление
byte  Drink = 25; // По умолчанию в рюмку наливаем  20 мл.
//----- Минимальные и максимальные значения наполняемой жидкости и задержки для наполнения. 
const byte  min_Drink = 2; // Минимум в рюмку - 2 мл.
const byte  max_Drink = 50; // Максимум в рюмку - 50 мл.
// Калибровка работы насосика. Значения для налива min_Drink и max_Drink соотвественно 
const unsigned int min_Drink_delay = 300; 
const unsigned int max_Drink_delay = 4000;
//--------
byte  DrinkCount = 1; //По умолчанию, для ручного режима - 1 рюмка
const byte  max_DrinkCount = 5; //Максимальное кол-во рюмок - 5
// Насосик
const byte PIN_PUMP = 12;
// Светодиоды
const int PIN_LED = 5;// Сюда подключаются светодиоды
const int LED_COUNT = max_DrinkCount;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN_LED, NEO_GRB + NEO_KHZ800);
//-------



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

void pump_disable() {
  digitalWrite(PIN_PUMP, 0);
}

void pump_timer(byte Drink) {
  digitalWrite(PIN_PUMP, 1);
  delay(map(Drink, min_Drink,  max_Drink, min_Drink_delay, max_Drink_delay));
  digitalWrite(PIN_PUMP, 0);
}

void oled_menu(int Menu) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("Y F K B D F N J H"), CENTER, 0);
  myOLED.print(F("F D N J"), CENTER, 15);
  myOLED.print(F("H E X Y J Q "), CENTER, 30);
  myOLED.print(F("G H J V S D R F"), CENTER, 45);
  myOLED.setFont(SmallFont);
  myOLED.print(F(">"), LEFT, (Menu * 15) + 15);
  myOLED.print(F("<"), RIGHT, (Menu * 15) + 15);
  myOLED.update();

}
//  выводит строчку по чуть чуть, в самый раз и тд. Передается номер строки, на которой выводить сообщение
void DrinkInfo(byte pos) {
  if (Drink < 15) {
    myOLED.print(F("YB J XTV"), CENTER, pos);
  } else if (Drink < 28) {
    myOLED.print(F("GJ XENM - XENM"), CENTER, pos);
  } else if (Drink < 38) {
    myOLED.print(F("D CFVSQ HFP"), CENTER, pos);
  } else if (Drink < 48) {
    myOLED.print(F("GJ GJKYJQ"), CENTER, pos);
  } else {
    myOLED.print(F("LJ RHFTD"), CENTER, pos);
  }

}

void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("DSGMTV"), CENTER, 20); //Выпьем
  // Рандом - 1
  switch (random(11)) {
    case 0:
      myOLED.print(F("PF LHEPTQ!"), CENTER, 40); //За друзей
      break;
    case 1:
      myOLED.print(F("PF VBKS{ LFV!"), CENTER, 40); //За милых дам
      break;
    case 2:
      myOLED.print(F("PF PLJHJDMT!"), CENTER, 40); //За здоровье
      break;
    case 3:
      myOLED.print(F("PF ELFXE!"), CENTER, 40); //За удачу
      break;
    case 4:
      myOLED.print(F("PF VBH DJ DCTV VBHT!"), CENTER, 40); //За мир во всем мире
      break;
    case 5:
      myOLED.print(F("PF NT{ RNJ D VJHT!"), CENTER, 40); //За тех кто в море
      break;
    case 6:
      myOLED.print(F("PF K><JDM !"), CENTER, 40); //За любовь !
      break;
    case 7:
      myOLED.print(F("PF RHFCJNE !"), CENTER, 40); //За красоту !
      break;
    case 8:
      myOLED.print(F("PF DTPTYBT !"), CENTER, 40); //За везение !
      break;
    case 9:
      myOLED.print(F("PF HJLBYE !"), CENTER, 40); //За родину !
      break;
    case 10:
      myOLED.print(F("PF YFC C DFVB"), CENTER, 38); //За нас с вами
      myOLED.print(F("B {HTY C YBVB !"), CENTER, 55); //И хрен с ними
      break;

  }
  myOLED.update();

}

// Меню Авто режим
void oled_auto(int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("F D N J"), CENTER, 0);
  myOLED.print(F("VK   "), RIGHT, 27);
  DrinkInfo(57);
  //  myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(Drink), CENTER, 13);
  myOLED.update();
}

// Меню Ручной режим
void oled_manual(int DrinkCount, int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("H E X Y J Q"), CENTER, 0);
  DrinkInfo(57);
  // myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.print(F("H>V"), 24, 27);
  myOLED.print(F("VK "), RIGHT, 27);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(DrinkCount), LEFT, 13);
  myOLED.print(String(Drink), (Drink < 10) ? 80 : 57, 13);
  myOLED.update();
}


void oled_naliv(int MenuFlag) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);

  myOLED.print(F("Y F K B D F > "), CENTER, 27);
  DrinkInfo(47);
  myOLED.update();
}

void oled_nalito(int MenuFlag, int Nalito) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);
  myOLED.print(F("Y F K B N J"), CENTER, 20);
  if (Nalito == 1) {
    myOLED.print(F("H > V R F"), CENTER, 55);
  } else if (Nalito <= 4 ) {
    myOLED.print(F("H > V R B"), CENTER, 55);
  } else {
    myOLED.print(F("H > V J R"), CENTER, 55);
  }

  myOLED.setFont(SmallFont);
  myOLED.print(String(Nalito), CENTER, 36);
  myOLED.update();
}

void ServoNaliv(byte rumka) {
  servo.attach(PIN_SERVO);
  for (int pos = servo.read(); pos <= Rumka_pos[rumka]; pos += 1) { 
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(10); // ждем 15 миллисекунд, пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();


}

void ServoParking () {
  //Serial.println(servo.read());
  servo.attach(PIN_SERVO);
  for (int pos = servo.read();  pos >= 0; pos -= 1) {
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(10); // ждем 15 миллисекунд, пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();
}

void CvetoMuzik() {
  for (int i = 0; i <= 7; i++) {
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(255, 0, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 255, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 0, 255));
      strip.show();
      delay(30);
    }
  }
}

void setup()  {
  //Serial.begin(9600);
  //  servo.attach(PIN_SERVO);
  pinMode(pin_SW, INPUT); // устанавливаем pin pin_SW как вход
  digitalWrite(pin_SW, HIGH); // Поддяжка вывода к 1
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  pinMode(PIN_PUMP, OUTPUT);
  digitalWrite(PIN_PUMP, 0);
  currentTime = millis();
  loopTime = currentTime;
  //   Volume=EEPROM.read(0);
  myOLED.begin();
  oled_menu(0);
  strip.begin();
  for (int i = 0; i < 5; i++) {
    pinMode(Optics[i], INPUT);
  }
  ServoParking();



}

void loop()  {
  currentTime = millis();
  if (currentTime >= (loopTime + 5)) { // проверяем каждые 5мс

    //     int  val = analogRead(0);     // считываем значение
    //  Serial.println(val);
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера
    if ((!encoder_A) && (encoder_A_prev)) {  // если состояние изменилось с положительного к нулю

      //Вращение влево
      if (encoder_B) {
        if (MenuFlag == 0) {
          (Menu <= 0 ) ? Menu = 2 : Menu--; // Перемещение курсора по главному меню назад
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink <= min_Drink ) ? Drink = max_Drink : Drink--; // Уменьшаем кол-во милилитров в рюмку
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (DrinkCount >= max_DrinkCount ) ? DrinkCount = 1 : DrinkCount++; // Влево увечичиваем рюмки для ручного режима
          oled_manual(DrinkCount, Drink);
        }
        //Вращение вправо
      } else {
        if (MenuFlag == 0) {
          (Menu >= 2 ) ? Menu = 0 : Menu++; // Перемещение курсора по главному меню вперед.
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_manual(DrinkCount, Drink);
        }
      }

    }

    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла

    int encoder_sw = digitalRead(pin_SW);
    if  (encoder_sw == 0 && encoder_sw != encoder_sw_prew)  { // Нажата кнопка

      int pause_sw = 0;
      boolean promivka = false;
      while (digitalRead(pin_SW) == 0) { // Держим кнопку. Считаем сколько времени прошло...
        delay(100);
        pause_sw++;
        if (pause_sw > 20 && Menu != 2 ) break;

        if (pause_sw > 20 && Menu == 2 && promivka == false) { // Если пункт меню промывка и держим кнопку больше 2 секунд.
          promivka = true;
          pump_enable(); // Включаем насос
          myOLED.clrScr();
          myOLED.setFont(RusFont);
          myOLED.print(F("G H J V S D R F"), CENTER, 15);
          myOLED.print(F(". . ."), CENTER, 45);
          myOLED.update();
        }
      }

      //После отпускания кнопки , обрабатываем
      if (promivka == true) { //Отпустили кнопку. Если включена промывка, выключаем насос и возвращаемся в главное меню
        promivka = false;
        pump_disable() ; //Выключаем насос
        oled_menu(2);

      } else {
        //Обработка всех нажатий кнопки
        if (Menu == 0 && MenuFlag == 0 &&  pause_sw < 10) { //Нажатие кнопки меню авто
          MenuFlag = 1;
          oled_auto(Drink);
        } else if (MenuFlag == 1 && pause_sw > 20) { //Выход из меню авто в главное
          MenuFlag = 0;
          oled_menu(0);
        } else if (MenuFlag == 1 ) { //Начинается автоматический разлив
          Serial.println("Начало автоматического разлива");
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          byte drink_count = 0;
          for (int y = 0; y < max_DrinkCount; y++) {
            if (analogRead(Optics[y]) > Optics_porog[y] ) {
              strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
              strip.show();
              ServoNaliv(y); // Перемещяемся к рюмке
              pump_timer(Drink); // Налив.
              strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
              strip.show();
              drink_count++;
            }
          }
          if (drink_count > 0) {
            oled_nalito(MenuFlag, drink_count );
            ServoParking();
            delay(1000);
            Tost();
            CvetoMuzik();
            oled_auto(Drink);
          } else {
            myOLED.clrScr();
            myOLED.setFont(RusFont);
            myOLED.print(F("YTN H>VJR !"), CENTER, 25);
            myOLED.update();
            delay(2000);
            oled_auto(Drink);

          }
        } else if (Menu == 1 && MenuFlag == 0 &&  pause_sw < 10) { // Нажатие меню ручное
          MenuFlag = 2;
          oled_manual(DrinkCount, Drink);
        } else if (MenuFlag == 2 && pause_sw > 20) { //Выход из меню ручное в главное
          MenuFlag = 0;
          oled_menu(1);
        } else if (MenuFlag == 2 ) { //Начинается ручной разлив
          //  Serial.println("Начало ручного разлива " + String(DrinkCount));
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          for (int y = 0; y < DrinkCount; y++) {
            strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
            strip.show();
            ServoNaliv(y); // Перемещяемся к рюмке
            pump_timer(Drink); // Налив.
            strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
            strip.show();
          }
          oled_nalito(MenuFlag, DrinkCount );
          ServoParking();
          Tost();
          CvetoMuzik();
          oled_manual(DrinkCount, Drink);
        }
      }
    }

    if (currentTime >= (ledTime + 300)) {
      //Опрашиваем оптопары ... Если рюмка поставлена , светодиод светится синим, нет ничего - не светится
      for (int i = 0; i < max_DrinkCount; i++) {
        
        int val = analogRead(Optics[i]);     // считываем значение
        Serial.println(val);
        if (val > Optics_porog[i]) {
          strip.setPixelColor(i, strip.Color(0, 0, 255));
        } else {
          strip.setPixelColor(i, strip.Color(0, 0, 0));
        }
    //    delay(20);

      }
      strip.show();
      ledTime = currentTime;
    }
    encoder_sw_prew = encoder_sw;
    loopTime = currentTime;

  }
}

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Теперь вообще все понятно! Вставлю пятак скетче для проверки/калибровки датчиков А0, А1, А2, А3, А6, А7. Все выводится в монитор порта.

void setup() {

  // Объявляем работу с последоватлеьным портом в самом начале
  Serial.begin(9600);
  // Теперь мы можем писать сообщения
  Serial.println ("Hello, Arduino Master");
}

void loop() {// Выводим таблицу с информацией о текущих значениях портов

  Serial.print("Port #\t\t");
  Serial.println("Value");
  Serial.print("A0\t\t");
  Serial.println(analogRead(A0));
  Serial.print("A1\t\t");
  Serial.println(analogRead(A1));
  Serial.print("A2\t\t");
  Serial.println(analogRead(A2));
  Serial.print("A3\t\t");
  Serial.println(analogRead(A3));
  Serial.print("A6\t\t");
  Serial.println(analogRead(A6));
  Serial.print("A7\t\t");
  Serial.println(analogRead(A7));
  Serial.println("--------");
  delay(5000);
}

 

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Вот идеальная машина для разлива )
https://youtu.be/BOQM5fZi3Wg

Автор красава, просто произведение искусства ))

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

У Афанасьева В. много поделок в стиле стимпанк, есть подробные ворклоги на технари.ру, в эту тему видел "насТРОение",  на Ютубе есть.

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

atom23rus пишет:

Парни, а подскажите как откалибровать насос?

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

/* StopWatch
 * Paul Badger 2008
 * Demonstrates using millis(), pullup resistors,
 * making two things happen at once, printing fractions
 *
 * Physical setup: momentary switch connected to pin 4, other side connected to ground
 * LED with series resistor between pin 13 and ground
 */


#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 4                 // button on pin 4
#define pumpPin 12 // pump on pin 12

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
int blinking;                       // condition for blinking - timer is timing
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time

void setup()
{
   Serial.begin(9600);

   pinMode(ledPin, OUTPUT);         // sets the digital pin as output

   pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
   digitalWrite(buttonPin, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.

}

void loop()
{
    // check for button press
   buttonState = digitalRead(buttonPin);                   // read the button state and store

   if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
      // if true then found a new button press while clock is not running - start the clock

      startTime = millis();                                   // store the start time
      blinking = true;                                     // turn on blinking while timing
      delay(5);                                               // short delay to debounce switch
      digitalWrite(pumpPin, HIGH); //pump ON
	  lastButtonState = buttonState;                          // store buttonState in lastButtonState, to compare next time

   }

   else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){     // check for a high to low transition
      // if true then found a new button press while clock is running - stop the clock and report

        elapsedTime =   millis() - startTime;              // store elapsed time
        blinking = false;                                  // turn off blinking, all done timing
        digitalWrite(pumpPin, LOW); // pump OFF
		lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time

       // routine to report elapsed time
        Serial.print( (int)(elapsedTime / 1000L));         // divide by 1000 to convert to seconds - then cast to an int to print

        Serial.print(".");                             // print decimal point

        // use modulo operator to get fractional part of time
       fractional = (int)(elapsedTime % 1000L);

       // pad in leading zeros - wouldn't it be nice if
       // Arduino language had a flag for this? :)
       if (fractional == 0)
          Serial.print("000");      // add three zero's
       else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
          Serial.print("00");       // add two zeros
       else if (fractional < 100)
          Serial.print("0");        // add one zero

       Serial.println(fractional);  // print fractional part of time

   }

   else{
      lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
   }

   // blink routine - blink the LED while timing
   // check to see if it's time to blink the LED; that is, the difference
   // between the current time and last time we blinked the LED is larger than
   // the interval at which we want to blink the LED.

   if ( (millis() - previousMillis > interval) ) {

      if (blinking == true){
         previousMillis = millis();                         // remember the last time we blinked the LED

         // if the LED is off turn it on and vice-versa.
         if (value == LOW)
            value = HIGH;
         else
            value = LOW;
         digitalWrite(ledPin, value);
      }
      else{
         digitalWrite(ledPin, LOW);                         // turn off LED when not blinking
      }
   }

}

 

atom23rus
Offline
Зарегистрирован: 06.08.2019

спасибо. на днях выложу систему как я расположил трубку!

 

atom23rus
Offline
Зарегистрирован: 06.08.2019

короче,по человечески загрузить не получилось.кидаю ссылки на картинки реализации поворота наливной головки.

den-a2rh
Offline
Зарегистрирован: 07.01.2018

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

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

atom23rus пишет:

короче,по человечески загрузить не получилось.кидаю ссылки на картинки реализации поворота наливной головки.

Нe не писающий мальчик, а так не плохо.

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

den-a2rh, прочитайте две последних страницы там все разъяснено. "Говорилка" пока в железе не опробована. Скетч с  МП3 в 105 сообщении.

atom23rus
Offline
Зарегистрирован: 06.08.2019

да боюсь писающего мальчика мужики не оценят

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Может кто нибудь подсказать как шрифт в кейсе тост побольше сделать?

den-a2rh
Offline
Зарегистрирован: 07.01.2018

Спасибо большое за подсказку...

den-a2rh
Offline
Зарегистрирован: 07.01.2018

А не могли бы вы помочь со схемой подключения и списком комплектующих... Я в этом не селен... Соответственно за вознаграждение.... Моя почта den260484@gmail.com Заранее спасибо

stpavel
Онлайн
Зарегистрирован: 09.10.2018

den-a2rh пишет:
А не могли бы вы помочь со схемой подключения и списком комплектующих... Я в этом не селен... Соответственно за вознаграждение.... Моя почта den260484@gmail.com Заранее спасибо

Схема подключения :
https://pikabu.ru/story/arduino_i_mp3_modul_uchim_arduino_govorit_3939974 

Где купить
https://ru.aliexpress.com/item/32659645208.html?spm=a2g0o.productlist.0.0.2d3b259fcpKTyq&algo_pvid=36ea7e3b-d25c-4ec1-a354-661eba1c9a7d&algo_expid=36ea7e3b-d25c-4ec1-a354-661eba1c9a7d-0&btsid=c29baa8c-f371-4e11-aa8f-2a3b5a9c2dd9&ws_ab_test=searchweb0_0,searchweb201602_1,searchweb201603_53 

Нужна еще sd карточка. 
На нее записываем файлы в папку mp3 файлы 0001.mp3 , 0002.mp3 итд
Это файлы с тостами.

Библиотека https://github.com/DFRobot/DFPlayer-Mini-mp3

​Последняя библиотека от DFRobot чето жрет памяти не хило. Если эта будет работать , почему бы и нет. 

В коде закоментировал процедуру tost которая выводила тосты на экран, и добавил маленькую процедурку tost которая просто проигрывает рандомный тост с сд карты. 

В настройках нужно поправить 

//mp3
byte mp3_count=11; //Количество голосовых файлов на SD карте

Код не тестировал, не на чем.  тут ничего сложного , должен работать, если не будет , поправим. 

#include <OLED_I2C.h>
#include <Servo.h>
#include "Adafruit_NeoPixel.h"
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>

OLED  myOLED(SDA, SCL, 8); //Подключение экрана А4, А5
extern uint8_t MegaNumbers[];
extern uint8_t RusFont[];
extern uint8_t SmallFont[];
unsigned long currentTime;
unsigned long loopTime;
unsigned long ledTime;
// Переменные для энкодера -----------
const int pin_A = 2;       // Подключение вывода A (CLK) энкодера
const int pin_B = 3;       // Подключение вывода B (DT) энкодера
const int pin_SW = 4;       // Подключение вывода кнопки (SW) энкодера
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev = 0;
unsigned char encoder_sw_prew = 1;
//Массив , обозначаем подключенные оптопары по выводам . Оптопары подключены, A0,A1,A2,A3,A6
const byte  Optics[] = {0, 1, 2, 3, 6};
// Значения порога срабатывания датчика для каждой рюмки
const unsigned int Optics_porog[] = {1000,1000,1000,1000,1000};
//Серво
const int PIN_SERVO = 9;
Servo servo;
//Позиция каждой рюмки ( mg995 max 250)
const byte Rumka_pos[] = {0,40,75,105,140};
const byte servo_speed=10; // Скорость поворота серво,  10 - норм, 20 медленно, 30 очень медленно
//-------------------------
byte  Menu = 0;
byte MenuFlag = 0; // Здесь храниться уровень меню. 0 находимся в  Главном меню. 1 Вошли в меню Авто, 2 вошли в  Ручное управление
byte  Drink = 25; // По умолчанию в рюмку наливаем  20 мл.
//----- Минимальные и максимальные значения наполняемой жидкости и задержки для наполнения. 
const byte  min_Drink = 2; // Минимум в рюмку - 2 мл.
const byte  max_Drink = 50; // Максимум в рюмку - 50 мл.
// Калибровка работы насосика. Значения для налива min_Drink и max_Drink соотвественно 
const unsigned int min_Drink_delay = 300; 
const unsigned int max_Drink_delay = 4000;
//--------
byte  DrinkCount = 1; //По умолчанию, для ручного режима - 1 рюмка
const byte  max_DrinkCount = 5; //Максимальное кол-во рюмок - 5
// Насосик
const byte PIN_PUMP = 12;
// Светодиоды
const int PIN_LED = 5;// Сюда подключаются светодиоды
const int LED_COUNT = max_DrinkCount;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN_LED, NEO_GRB + NEO_KHZ800);
//mp3
byte mp3_count=11; //Количество голосовых файлов на SD карте



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

void pump_disable() {
  digitalWrite(PIN_PUMP, 0);
}

void pump_timer(byte Drink) {
  digitalWrite(PIN_PUMP, 1);
  delay(map(Drink, min_Drink,  max_Drink, min_Drink_delay, max_Drink_delay));
  digitalWrite(PIN_PUMP, 0);
}

void oled_menu(int Menu) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("Y F K B D F N J H"), CENTER, 0);
  myOLED.print(F("F D N J"), CENTER, 15);
  myOLED.print(F("H E X Y J Q "), CENTER, 30);
  myOLED.print(F("G H J V S D R F"), CENTER, 45);
  myOLED.setFont(SmallFont);
  myOLED.print(F(">"), LEFT, (Menu * 15) + 15);
  myOLED.print(F("<"), RIGHT, (Menu * 15) + 15);
  myOLED.update();

}
//  выводит строчку по чуть чуть, в самый раз и тд. Передается номер строки, на которой выводить сообщение
void DrinkInfo(byte pos) {
  if (Drink < 15) {
    myOLED.print(F("YB J XTV"), CENTER, pos);
  } else if (Drink < 28) {
    myOLED.print(F("GJ XENM - XENM"), CENTER, pos);
  } else if (Drink < 38) {
    myOLED.print(F("D CFVSQ HFP"), CENTER, pos);
  } else if (Drink < 48) {
    myOLED.print(F("GJ GJKYJQ"), CENTER, pos);
  } else {
    myOLED.print(F("LJ RHFTD"), CENTER, pos);
  }

}
/*
void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("DSGMTV"), CENTER, 20); //Выпьем
  // Рандом - 1
  switch (random(11)) {
    case 0:
      myOLED.print(F("PF LHEPTQ!"), CENTER, 40); //За друзей
      break;
    case 1:
      myOLED.print(F("PF VBKS{ LFV!"), CENTER, 40); //За милых дам
      break;
    case 2:
      myOLED.print(F("PF PLJHJDMT!"), CENTER, 40); //За здоровье
      break;
    case 3:
      myOLED.print(F("PF ELFXE!"), CENTER, 40); //За удачу
      break;
    case 4:
      myOLED.print(F("PF VBH DJ DCTV VBHT!"), CENTER, 40); //За мир во всем мире
      break;
    case 5:
      myOLED.print(F("PF NT{ RNJ D VJHT!"), CENTER, 40); //За тех кто в море
      break;
    case 6:
      myOLED.print(F("PF K><JDM !"), CENTER, 40); //За любовь !
      break;
    case 7:
      myOLED.print(F("PF RHFCJNE !"), CENTER, 40); //За красоту !
      break;
    case 8:
      myOLED.print(F("PF DTPTYBT !"), CENTER, 40); //За везение !
      break;
    case 9:
      myOLED.print(F("PF HJLBYE !"), CENTER, 40); //За родину !
      break;
    case 10:
      myOLED.print(F("PF YFC C DFVB"), CENTER, 38); //За нас с вами
      myOLED.print(F("B {HTY C YBVB !"), CENTER, 55); //И хрен с ними
      break;

  }
  myOLED.update();

}
*/

void Tost() {
 randomSeed(currentTime);
 mp3_play(random(mp3_count));
 delay (5000);
}

// Меню Авто режим
void oled_auto(int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("F D N J"), CENTER, 0);
  myOLED.print(F("VK   "), RIGHT, 27);
  DrinkInfo(57);
  //  myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(Drink), CENTER, 13);
  myOLED.update();
}

// Меню Ручной режим
void oled_manual(int DrinkCount, int Drink) {

  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("H E X Y J Q"), CENTER, 0);
  DrinkInfo(57);
  // myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.print(F("H>V"), 24, 27);
  myOLED.print(F("VK "), RIGHT, 27);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(DrinkCount), LEFT, 13);
  myOLED.print(String(Drink), (Drink < 10) ? 80 : 57, 13);
  myOLED.update();
}


void oled_naliv(int MenuFlag) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);

  myOLED.print(F("Y F K B D F > "), CENTER, 27);
  DrinkInfo(47);
  myOLED.update();
}

void oled_nalito(int MenuFlag, int Nalito) {
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print((MenuFlag == 1) ? F("F D N J") : F("H E X Y J Q") , CENTER, 0);
  myOLED.print(F("Y F K B N J"), CENTER, 20);
  if (Nalito == 1) {
    myOLED.print(F("H > V R F"), CENTER, 55);
  } else if (Nalito <= 4 ) {
    myOLED.print(F("H > V R B"), CENTER, 55);
  } else {
    myOLED.print(F("H > V J R"), CENTER, 55);
  }

  myOLED.setFont(SmallFont);
  myOLED.print(String(Nalito), CENTER, 36);
  myOLED.update();
}

void ServoNaliv(byte rumka) {
  servo.attach(PIN_SERVO);
  for (int pos = servo.read(); pos <= Rumka_pos[rumka]; pos += 1) { 
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(servo_speed); // ждем , пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();


}

void ServoParking () {
  //Serial.println(servo.read());
  servo.attach(PIN_SERVO);
  for (int pos = servo.read();  pos >= 0; pos -= 1) {
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(servo_speed); // ждем , пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();
}

void CvetoMuzik() {
  for (int i = 0; i <= 7; i++) {
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(255, 0, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 255, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 0, 255));
      strip.show();
      delay(30);
    }
  }
}

void setup()  {
  Serial.begin(9600);
  mp3_set_serial (Serial); 
  delay(100);
  mp3_set_volume (25);
  delay(100);
  pinMode(pin_SW, INPUT); // устанавливаем pin pin_SW как вход
  digitalWrite(pin_SW, HIGH); // Поддяжка вывода к 1
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  pinMode(PIN_PUMP, OUTPUT);
  digitalWrite(PIN_PUMP, 0);
  currentTime = millis();
  loopTime = currentTime;
  //   Volume=EEPROM.read(0);
  myOLED.begin();
  oled_menu(0);
  strip.begin();
  for (int i = 0; i < 5; i++) {
    pinMode(Optics[i], INPUT);
  }
  
  ServoParking();



}

void loop()  {
  currentTime = millis();
  if (currentTime >= (loopTime + 5)) { // проверяем каждые 5мс

    //     int  val = analogRead(0);     // считываем значение
    //  Serial.println(val);
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера
    if ((!encoder_A) && (encoder_A_prev)) {  // если состояние изменилось с положительного к нулю

      //Вращение влево
      if (encoder_B) {
        if (MenuFlag == 0) {
          (Menu <= 0 ) ? Menu = 2 : Menu--; // Перемещение курсора по главному меню назад
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink <= min_Drink ) ? Drink = max_Drink : Drink--; // Уменьшаем кол-во милилитров в рюмку
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (DrinkCount >= max_DrinkCount ) ? DrinkCount = 1 : DrinkCount++; // Влево увечичиваем рюмки для ручного режима
          oled_manual(DrinkCount, Drink);
        }
        //Вращение вправо
      } else {
        if (MenuFlag == 0) {
          (Menu >= 2 ) ? Menu = 0 : Menu++; // Перемещение курсора по главному меню вперед.
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_manual(DrinkCount, Drink);
        }
      }

    }

    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла

    int encoder_sw = digitalRead(pin_SW);
    if  (encoder_sw == 0 && encoder_sw != encoder_sw_prew)  { // Нажата кнопка

      int pause_sw = 0;
      boolean promivka = false;
      while (digitalRead(pin_SW) == 0) { // Держим кнопку. Считаем сколько времени прошло...
        delay(100);
        pause_sw++;
        if (pause_sw > 20 && Menu != 2 ) break;

        if (pause_sw > 20 && Menu == 2 && promivka == false) { // Если пункт меню промывка и держим кнопку больше 2 секунд.
          promivka = true;
          pump_enable(); // Включаем насос
          myOLED.clrScr();
          myOLED.setFont(RusFont);
          myOLED.print(F("G H J V S D R F"), CENTER, 15);
          myOLED.print(F(". . ."), CENTER, 45);
          myOLED.update();
        }
      }

      //После отпускания кнопки , обрабатываем
      if (promivka == true) { //Отпустили кнопку. Если включена промывка, выключаем насос и возвращаемся в главное меню
        promivka = false;
        pump_disable() ; //Выключаем насос
        oled_menu(2);

      } else {
        //Обработка всех нажатий кнопки
        if (Menu == 0 && MenuFlag == 0 &&  pause_sw < 10) { //Нажатие кнопки меню авто
          MenuFlag = 1;
          oled_auto(Drink);
        } else if (MenuFlag == 1 && pause_sw > 20) { //Выход из меню авто в главное
          MenuFlag = 0;
          oled_menu(0);
        } else if (MenuFlag == 1 ) { //Начинается автоматический разлив
         // Serial.println("Начало автоматического разлива");
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          byte drink_count = 0;
          for (int y = 0; y < max_DrinkCount; y++) {
            if (analogRead(Optics[y]) > Optics_porog[y] ) {
              strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
              strip.show();
              ServoNaliv(y); // Перемещяемся к рюмке
              pump_timer(Drink); // Налив.
              strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
              strip.show();
              drink_count++;
            }
          }
          if (drink_count > 0) {
            oled_nalito(MenuFlag, drink_count );
            ServoParking();
            delay(1000);
            Tost();
            CvetoMuzik();
            oled_auto(Drink);
          } else {
            myOLED.clrScr();
            myOLED.setFont(RusFont);
            myOLED.print(F("YTN H>VJR !"), CENTER, 25);
            myOLED.update();
            delay(2000);
            oled_auto(Drink);

          }
        } else if (Menu == 1 && MenuFlag == 0 &&  pause_sw < 10) { // Нажатие меню ручное
          MenuFlag = 2;
          oled_manual(DrinkCount, Drink);
        } else if (MenuFlag == 2 && pause_sw > 20) { //Выход из меню ручное в главное
          MenuFlag = 0;
          oled_menu(1);
        } else if (MenuFlag == 2 ) { //Начинается ручной разлив
          //  Serial.println("Начало ручного разлива " + String(DrinkCount));
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          for (int y = 0; y < DrinkCount; y++) {
            strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
            strip.show();
            ServoNaliv(y); // Перемещяемся к рюмке
            pump_timer(Drink); // Налив.
            strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
            strip.show();
          }
          oled_nalito(MenuFlag, DrinkCount );
          ServoParking();
          Tost();
          CvetoMuzik();
          oled_manual(DrinkCount, Drink);
        }
      }
    }

    if (currentTime >= (ledTime + 300)) {
      //Опрашиваем оптопары ... Если рюмка поставлена , светодиод светится синим, нет ничего - не светится
      for (int i = 0; i < max_DrinkCount; i++) {
        
        int val = analogRead(Optics[i]);     // считываем значение
     //   Serial.println("A"+String(Optics[i])+"="+val);
        if (val > Optics_porog[i]) {
          strip.setPixelColor(i, strip.Color(0, 0, 255));
        } else {
          strip.setPixelColor(i, strip.Color(0, 0, 0));
        }
    //    delay(20);

      }
      strip.show();
      ledTime = currentTime;
    }
    encoder_sw_prew = encoder_sw;
    loopTime = currentTime;

  }
}

 

den-a2rh
Offline
Зарегистрирован: 07.01.2018

Спасибо вам большое.... Буду пробовать

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Небольшая поправочка

В процедуре tost вместо

 mp3_play(random(mp3_count));

должно быть

 mp3_play(random(mp3_count)+1);

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

den-a2rh ! В скетче предоставленного stpavel все подробно описано:
-Arduino pro mini 328 5v или аналогичный;
-дисплей OLED 0,96 I2C 128x64, подключается к А4 (SDA), А5 (SCL), VCC, GND;
-энкодер РЕС11 с кнопкой или аналогичный, подключается к D2 (A), D3 (B), D3 (E), C и D (GND),подтягивающие резисторы 2шт. 10кОм к D2, D3 одним концом, другим к VCC;
-лента светодиодная пиксельная WS2812B 5V используется 5 светодиодов, подключается к D5 (Din), GND  (GND), +5V и GND к внешнему источнику питания;
-серва (я использую SG90), подключается D9 (желтый), VCC (красный), GND (коричневый);
-насос (386 6-12V, нормально работает от 5 вольт, потребление 150мА), через силовой ключ или реле,

https://umnyjdomik.ru/silovoj-kljuch-5-a-24-v-na-polevom-tranzistore-irf520-mosfet-dlya-arduino.html

подключается к D12 (in), GND и к +5V и GND к внешнему источнику питания ;
-оптодатчики ( см. схему 1) 5 шт, подключаются к аналоговым входам А0, А1,А2,А3,А6  и VCC, GND

 

соответственно, схема 1для датчиков можно использовать пару  ИК светодиод + ИК фототранзистор с одинаковоу длинной волны, резистор для светодиода подбирается в зависимости от тока 470Ом,  резистор фототранзистора 10кОм, или купить готовую как на рисунке ;
-организация питания: литий 18680 8800ммА (Реально 3300мА), с зарядником ТР4056, и повышающим регулируемым модулем (Преобразователь DC-DC MT3608)  настроен на 5 вольт, выход модуля . Если лента и насос запитывается от 12В, то эти 12в подаются на пин RAW Ардуины.
*- DFPlayer mini (MP3-TF-16P) подключается:

VCC  DFP (1) к  5v внешнего источника питания,GND DFP (7) c GND Arduino и внешнему источнику питания,RX DFP (2)c TX Arduino (D0) через резистор 1кОм, TX DFP (3) c RX Arduino (D1) через резистор 1кОм, SPK_1 DFP(6) и SPK_2  DFP(8) к  динамику.

Рекомендую вам самому попробовать начертить схему наливатора в SPlan70, представить сюда, а результат обсудим.

den-a2rh
Offline
Зарегистрирован: 07.01.2018

Спасибо большое.... Всё доступно обьяснили... Буду пробовать

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

den-a2rh пишет:
Спасибо большое.... Всё доступно обьяснили... Буду пробовать

а плейер есть?

den-a2rh
Offline
Зарегистрирован: 07.01.2018

На днях должен прийти с алиэкспресс... Ещё не все комплектующие пришли

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

den-a2rh, отправил вам на почту нарезку тостов, если кому еще понадобиться, почта моя  forthomo@yandex.ru пишите.

den-a2rh
Offline
Зарегистрирован: 07.01.2018

Спасибо большое за нарезку тостов

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Вот такая ерунда происходит:

//		                     	задаю			на самом деле	 			так должно быть	
const byte Rumka_pos[] = {3,50,98,145,179}; // 12 - 48 - 90 - 135 - 174 (8 - 49 - 90 -132 - 173 - по чертежам)
//				                                 36   32    45    29       41   41  41    41 

 серва самая дешевая.   У кого какие мысли?

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Поправил скетч для калибровки насоса

#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 4                 // button on pin 4
#define pumpPin 12 // pump on pin 12

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
int blinking;                       // condition for blinking - timer is timing
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time

void setup()
{
   Serial.begin(9600);

   pinMode(ledPin, OUTPUT);         // sets the digital pin as output
   pinMode(pumpPin, OUTPUT); 
   pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
   digitalWrite(buttonPin, 1);   // turn on pullup resistors. Wire button so that press shorts pin to ground.

}

void loop()
{
    // check for button press
   buttonState = digitalRead(buttonPin);                   // read the button state and store

   if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
      // if true then found a new button press while clock is not running - start the clock

      startTime = millis();                                   // store the start time
      blinking = true;                                     // turn on blinking while timing
      delay(5);                                               // short delay to debounce switch
      digitalWrite(pumpPin, 1); //pump ON
	  lastButtonState = buttonState;                          // store buttonState in lastButtonState, to compare next time

   }

   else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){     // check for a high to low transition
      // if true then found a new button press while clock is running - stop the clock and report

        elapsedTime =   millis() - startTime;              // store elapsed time
        blinking = false;                                  // turn off blinking, all done timing
        digitalWrite(pumpPin, 0); // pump OFF
		lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time

       // routine to report elapsed time
        Serial.print( (int)(elapsedTime / 1000L));         // divide by 1000 to convert to seconds - then cast to an int to print

        Serial.print(".");                             // print decimal point

        // use modulo operator to get fractional part of time
       fractional = (int)(elapsedTime % 1000L);

       // pad in leading zeros - wouldn't it be nice if
       // Arduino language had a flag for this? :)
       if (fractional == 0)
          Serial.print("000");      // add three zero's
       else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
          Serial.print("00");       // add two zeros
       else if (fractional < 100)
          Serial.print("0");        // add one zero

       Serial.println(fractional);  // print fractional part of time

   }

   else{
      lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
   }

   // blink routine - blink the LED while timing
   // check to see if it's time to blink the LED; that is, the difference
   // between the current time and last time we blinked the LED is larger than
   // the interval at which we want to blink the LED.

   if ( (millis() - previousMillis > interval) ) {

      if (blinking == true){
         previousMillis = millis();                         // remember the last time we blinked the LED

         // if the LED is off turn it on and vice-versa.
         if (value == LOW)
            value = HIGH;
         else
            value = LOW;
         digitalWrite(ledPin, value);
      }
      else{
         digitalWrite(ledPin, LOW);                         // turn off LED when not blinking
      }
   }

}

 

RW3
RW3 аватар
Offline
Зарегистрирован: 07.08.2019

Схема под скетч с первой страницы http://arduino.ru/sites/default/files/u49308/skhema-1.jpg
может кому пригодится

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Коллеги есть предложение использовать LCD 1602 I2C, на OLED шрифт мелкий, а "дедушка старенький, глазки слабенькие". Русский шрифт есть, вчера пытал.

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Да, тоже давно об этом думал. Ломать глаза на мизерном олед дисплейчике как то не айс

Заказал сегодня , жду когда придет, буду переделывать под него. 

Вобще много идей , как должен будет выглядить мой будущий наливатор. Идею с поворачивающимся кранчиком отбросил, не нравиться мне она. Будет вращаться стол. Обязательно будет сосуд сверху, в который будет предварительно заливаться алкоголь. Никаких там трубочек торчащих и засунутых в бутылку. Вдохновил меня этот видос, который я выкладывал несколько сообщений назад. 

 

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

stpavel пишет:

Да, тоже давно об этом думал. Ломать глаза на мизерном олед дисплейчике как то не айс

Помоги менюху написать для LCD1602 заготовку прилагаю , блок ТОСТ еще не готов.

#include <LCD_1602_RUS.h>
#include <Servo.h>
#include "Adafruit_NeoPixel.h"
#include <SoftwareSerial.h>//добавляем библиотеки
#include <DFPlayer_Mini_Mp3.h>//добавляем библиотеку МП3 плейера

LCD_1602_RUS lcd(0x27, 16, 2); //Подключение экрана А4-SDA-зеленый, А5-SCL-желтый

unsigned long currentTime;
unsigned long loopTime;
unsigned long ledTime;

// Переменные для энкодера -----------
const int pin_A = 2;       // Подключение вывода A (CLK) энкодера
const int pin_B = 3;       // Подключение вывода B (DT) энкодера
const int pin_SW = 4;       // Подключение вывода кнопки (SW) энкодера
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev = 0;
unsigned char encoder_sw_prew = 1;
//Массив , обозначаем подключенные оптопары по выводам . Оптопары подключены, A0,A1,A2,A3,A6
const byte  Optics[] = {0, 1, 2, 3, 6};
// Значения порога срабатывания датчика для каждой рюмки
const unsigned int Optics_porog[] = {100,200,200,200,100};
//Серво
const int PIN_SERVO = 9;
Servo servo;
//Позиция каждой рюмки 
const byte Rumka_pos[] = {3,50,98,145,179}; //12 - 48 - 90 - 135 - 174 
const byte servo_speed=20; // Скорость поворота серво,  10 - норм, 20 медленно, 30 очень медленно
byte  Menu = 0;
byte MenuFlag = 0; // Здесь храниться уровень меню. 0 находимся в  Главном меню. 1 Вошли в меню Авто, 2 вошли в  Ручное управление
byte  Drink = 25; // По умолчанию в рюмку наливаем  20 мл.
//----- Минимальные и максимальные значения наполняемой жидкости и задержки для наполнения. 
const byte  min_Drink = 2; // Минимум в рюмку - 2 мл.
const byte  max_Drink = 50; // Максимум в рюмку - 50 мл.
// Калибровка работы насосика. Значения для налива min_Drink и max_Drink соотвественно 
const unsigned int min_Drink_delay = 222; 
const unsigned int max_Drink_delay = 5500;
//--------
byte  DrinkCount = 1; //По умолчанию, для ручного режима - 1 рюмка
const byte  max_DrinkCount = 5; //Максимальное кол-во рюмок - 5
// Насосик
const byte PIN_PUMP = 12;
// Светодиоды
const int PIN_LED = 5;// Сюда подключаются светодиоды
const int LED_COUNT = max_DrinkCount;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN_LED, NEO_GRB + NEO_KHZ800);
//-------



void pump_enable() {
  digitalWrite(PIN_PUMP, 1); //вкл реле
}

void pump_disable() {
  digitalWrite(PIN_PUMP, 0); //выкл реле
}

void pump_timer(byte Drink) {
  digitalWrite(PIN_PUMP, 1); //вкл реле
  delay(map(Drink, min_Drink,  max_Drink, min_Drink_delay, max_Drink_delay));
  digitalWrite(PIN_PUMP, 0); //выкл реле
}

void oled_menu(int Menu) {
  lcd.setCursor(3, 0);
  lcd.print("HАЛИВАТОР");
  lcd.setCursor(2, 0);
  lcd.print("<   АВТО   >");
//lcd.print("<  РУЧНОЙ  >");
//lcd.print("< ПРОМЫВКА >");
 
}
//  выводит строчку по чуть чуть, в самый раз и тд. Передается номер строки, на которой выводить сообщение
void DrinkInfo(byte pos) {
  lcd.setCursor(0, 0);
  lcd.print("HАЛИТЬ  ПО");
  lcd.setCursor(11, 0);
  lcd.print(Drink);
  lcd.setCursor(14, 0);
  lcd.print("мЛ"); 
  if (Drink < 15) {
    lcd.setCursor(5, 1);
    lcd.print("НИ О ЧЕМ");
  } else if (Drink < 28) {
    lcd.setCursor(2, 1);
    lcd.print("ПО ЧУТЬ - ЧУТЬ");
  } else if (Drink < 38) {
    lcd.setCursor(2, 1);
    lcd.print("В САМЫЙ  РАЗ");
  } else if (Drink < 48) {
    lcd.setCursor(3, 1);
    lcd.print("ПО  ПОЛНОЙ");
  } else {
    lcd.setCursor(4, 1);
    lcd.print("ДО КРАЕВ");
  }
}

/*
void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("DSGMTV"), CENTER, 20); //Выпьем
  // Рандом - 1
  switch (random(11)) {
    case 0:
      myOLED.print(F("PF LHEPTQ!"), CENTER, 40); //За друзей
      break;
    case 1:
      myOLED.print(F("PF VBKS{ LFV!"), CENTER, 40); //За милых дам
      break;
    case 2:
      myOLED.print(F("PF PLJHJDMT!"), CENTER, 40); //За здоровье
      break;
    case 3:
      myOLED.print(F("PF ELFXE!"), CENTER, 40); //За удачу
      break;
    case 4:
      myOLED.print(F("PF VBH DJ DCTV VBHT!"), CENTER, 40); //За мир во всем мире
      break;
    case 5:
      myOLED.print(F("PF NT{ RNJ D VJHT!"), CENTER, 40); //За тех кто в море
      break;
    case 6:
      myOLED.print(F("PF K><JDM !"), CENTER, 40); //За любовь !
      break;
    case 7:
      myOLED.print(F("PF RHFCJNE !"), CENTER, 40); //За красоту !
      break;
    case 8:
      myOLED.print(F("PF DTPTYBT !"), CENTER, 40); //За везение !
      break;
    case 9:
      myOLED.print(F("PF HJLBYE !"), CENTER, 40); //За родину !
      break;
    case 10:
      myOLED.print(F("PF YFC C DFVB"), CENTER, 38); //За нас с вами
      myOLED.print(F("B {HTY C YBVB !"), CENTER, 55); //И хрен с ними
      break;

  }
  myOLED.update();

}
*/

/*
  void Tost() {
  randomSeed(currentTime);
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("YE?"), CENTER, 20); //НУ,
   Рандом - 1
  switch (random(18)) { // 0...17
    case 0:
      myOLED.print(F("PF DCNHTXE!"), CENTER, 40); //ЗА ВСТРЕЧУ!
      mp3_play (2);  // Проигрываем "mp3/0002.mp3"
    delay(100);
    mp3_stop();
    break;
    case 1:
      myOLED.print(F("PF RHFCJNE!"), CENTER, 40); //ЗА КРАСОТУ!
      mp3_play (3);  // Проигрываем "mp3/0003.mp3"
    delay(100);
    mp3_stop();
    break;
  case 2:
      myOLED.print(F("PF LHE;,E!"), CENTER, 40); //ЗА ДРУЖБУ!
      mp3_play (4);  // Проигрываем "mp3/0004.mp3"
    delay(100);
    mp3_stop();
    break;
  case 4:
      myOLED.print(F("PF ,HFNCNDJ!"), CENTER, 40); //ЗА БРАТСТВО!
      mp3_play (5);  // Проигрываем "mp3/0005.mp3"
    delay(100);
    mp3_stop();
    break;
  case 5:
      myOLED.print(F("PF"), CENTER, 38); //за
    myOLED.print(F("CGHFDTLKBDJCNM!"), CENTER, 55); //СПРАВЕДЛИВОСТЬ!
      mp3_play (6);  // Проигрываем "mp3/0006.mp3"
    delay(100);
    mp3_stop();
    break;
    case 6:
      myOLED.print(F("PF HS,FKRE!"), CENTER, 40); //ЗА РЫБАЛКУ!
      mp3_play (7);  // Проигрываем "mp3/0007.mp3"
    delay(100);
    mp3_stop();
    break;
  case 7:
      myOLED.print(F("PF BCRECCNDJ!"), CENTER, 40); //ЗА ИСКУССТВО!
      mp3_play (8);  // Проигрываем "mp3/0008.mp3"
    delay(100);
    mp3_stop();
    break;
  case 8:
      myOLED.print(F("PF HFPEV!"), CENTER, 40); //ЗА РАЗУМ!
      mp3_play (9);  // Проигрываем "mp3/0009.mp3"
    delay(100);
    mp3_stop();
    break; 
  case 9:
      myOLED.print(F("PF BCNBYYS["), CENTER, 38); //ЗА ИСТИННЫХ
      myOLED.print(F(";tyoby!"), CENTER, 55); //ЖЕНЩИН!
      mp3_play (10);  // Проигрываем "mp3/0010.mp3"
    delay(100);
    mp3_stop();
    break;
  case 10:
      myOLED.print(F("PF GJYBVFYBT!"), CENTER, 40); //ЗА ПОНИМАНИЕ!
      mp3_play (11);  // Проигрываем "mp3/0011.mp3"
    delay(100);
    mp3_stop();
    break;
  case 11:
      myOLED.print(F("PF TLBYTYBT!"), CENTER, 40); //ЗА ЕДИНЕНИЕ!
      mp3_play (13);  // Проигрываем "mp3/0013.mp3"
    delay(100);
    mp3_stop();
    break;
  case 12:
      myOLED.print(F("PF GJ,TLE!"), CENTER, 40); //ЗА ПОБЕДУ!
      mp3_play (16);  // Проигрываем "mp3/0016.mp3"
    delay(100);
    mp3_stop();
    break;
  case 13:
      myOLED.print(F("PF HJLBYE!"), CENTER, 40); //ЗА РОДИНУ!
      mp3_play (21);  // Проигрываем "mp3/0021.mp3"
    delay(100);
    mp3_stop();
    break;
  case 14:
      myOLED.print(F("XNJ, UJKJDF"), CENTER, 38); //ЧТОБ ГОЛОВА
    myOLED.print(F("YT NHTOFKF!"), CENTER, 55); //НЕ ТРЕЩАЛА!
      mp3_play (17);  // Проигрываем "mp3/0017.mp3"
    delay(100);
    mp3_stop();
    break;
  case 15:
      myOLED.print(F("PF CJKBLYJT"), CENTER, 38); //ЗА СОЛИДНОЕ
    myOLED.print(F("VE;CRJT VJKXFYBT"), CENTER, 55); //МУЖСКОЕ МОЛЧАНИЕ
      mp3_play (12);  // Проигрываем "mp3/0012.mp3"
    delay(100);
    mp3_stop();
    break;
  case 16:
      myOLED.print(F("XNJ, VJHOBKJ"), CENTER, 38); //ЧТОБ МОРЩИЛО
    myOLED.print(F("YFC VTYMIT!"), CENTER, 55); //НАС МЕНЬШЕ!
      mp3_play (18);  // Проигрываем "mp3/0018.mp3"
    delay(100);
    mp3_stop();
    break;
  case 17:
      myOLED.print(F("XNJ, D CNJHJYE"), CENTER, 38); //ЧТОБ В СТОРОНУ
    myOLED.print(F("YT DBKMYEKJ!"), CENTER, 55); //НЕ ВИЛЬНУЛО!
      mp3_play (19);  // Проигрываем "mp3/0019.mp3"
    delay(100);
    mp3_stop();
    break;      
  }
  myOLED.update();

}
*/
// Меню Авто режим
void oled_auto(int Drink) {
  lcd.setCursor(0, 0);
    lcd.print("HАЛИТЬ ПО");
    lcd.setCursor(11, 0);
    lcd.print(Drink);
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
    DrinkInfo(57);
  //  myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  
}

// Меню Ручной режим
void oled_manual(int DrinkCount, int Drink) {
  lcd.setCursor(0, 0);
    lcd.print("HАЛИТЬ ПО");
    lcd.setCursor(11, 0);
    lcd.print(Drink);
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
    DrinkInfo(57);
}
  
/*
  myOLED.clrScr();
  myOLED.setFont(RusFont);
  myOLED.print(F("H E X Y J Q"), CENTER, 0); //Р У Ч Н О Й 
  DrinkInfo(57);
  // myOLED.print(DrinkInfo[map(Drink, 2, max_Drink, 0, 4)], CENTER, 57);
  myOLED.print(F("H>V"), 24, 27);
  myOLED.print(F("VK "), RIGHT, 27);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(DrinkCount), LEFT, 13);
  myOLED.print(String(Drink), (Drink < 10) ? 80 : 57, 13);
  myOLED.update();
}
*/

void oled_naliv(int MenuFlag) {
  lcd.setCursor(0, 0);
    lcd.print("HАЛИВАЮ ПО");
    lcd.setCursor(11, 0);
    lcd.print(Drink);
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
  lcd.setCursor(3, 1);
    lcd.print("В");
    lcd.setCursor(5, 1);
    lcd.print(DrinkCount);  
  if (DrinkCount == 1) {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКУ");
  } else if (DrinkCount <= 4 ) {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКИ");
  } else {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКИ");
  }
}

void oled_nalito(int MenuFlag, int Nalito) {
    lcd.setCursor(0, 0);
    lcd.print("HАЛИТО  ПО");
    lcd.setCursor(11, 0);
    lcd.print(Drink);
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
  lcd.setCursor(3, 1);
    lcd.print("В");
    lcd.setCursor(5, 1);
    lcd.print(Nalito);  
  if (Nalito == 1) {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКУ");
  } else if (Nalito <= 4 ) {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКИ");
  } else {
    lcd.setCursor(7, 1);
    lcd.print("РЮМКИ");
  }

}
void ServoNaliv(byte rumka) {
  servo.attach(PIN_SERVO);
  for (int pos = servo.read(); pos <= Rumka_pos[rumka]; pos += 1) { 
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(servo_speed); // ждем , пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();


}

void ServoParking () {
  //Serial.println(servo.read());
  servo.attach(PIN_SERVO);
  for (int pos = servo.read();  pos >= 0; pos -= 1) {
    // с шагом в 1 градус
    servo.write(pos); // даем серве команду повернуться в положение, которое задается в переменной 'pos'
    delay(servo_speed); // ждем , пока ротор сервы выйдет в заданную позицию
  }
  servo.detach();
}

void CvetoMuzik() {
  for (int i = 0; i <= 7; i++) {
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(255, 0, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 255, 0));
      strip.show();
      delay(30);
    }
    for (int y = 0; y < max_DrinkCount; y++) {
      strip.setPixelColor(y, strip.Color(0, 0, 255));
      strip.show();
      delay(30);
    }
  }
}

void setup()  {
  Serial.begin(9600);//
  //устанавливаем Serial порт МП3 плейера если вывод в монитор TX(D0) и RX(D1)не нужен 
  mp3_set_serial (Serial);//инициализируем Serial порт МП3 плейера
  /*  
  при необходимости создаем програмный порт для управдения МП3 плейером, если вывод в монитор TX(D0) RX(D1) необходим
  SoftwareSerial mySoftwareSerial(10, 11); // RX, TX  обозначаем програмный порт как mySoftwareSerial
  //плейер подключаем D10 D11
  mySoftwareSerial.begin(9600);//инициализируем програмный Serial порт 
  mp3_set_serial (mySoftwareSerial);// указываем програмный порт для МП3 плейера
  //инициализируем Serial с скоростью 115200, если вывод в монитор  TX(D0) RX(D1) необходим 
  Serial.begin(115200);
  */  
  delay (100);//Между двумя командами необходимо делать задержку 100 миллисекунд, в противном случае некоторые команды могут работать не стабильно.
  mp3_set_volume (25);// устанвливаем громкость 25
  delay (100);
  mp3_play (1); // Проигрываем "mp3/0001.mp3"(0001_get started!.mp3)
  delay (100);
  //   Volume=EEPROM.read(0);
  
  /*
  
  myOLED.begin(); // Инициализация дисплея
  // выводим привествие после включения перед наливом
  myOLED.clrScr();  
  myOLED.setFont(RusFont);
  myOLED.print(F("Ye? yfxfkb!"), CENTER, 50);// Ну, начали!
  myOLED.update(); 
  
  */
  lcd.init();// initialize the lcd
  lcd.backlight();
  pinMode(pin_SW, INPUT); // устанавливаем pin pin_SW как вход
  digitalWrite(pin_SW, HIGH); // Поддяжка вывода к 1
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  pinMode(PIN_PUMP, OUTPUT);
  digitalWrite(PIN_PUMP, 0);
  currentTime = millis();
  loopTime = currentTime;
  //---------------

  oled_menu(0);
  strip.begin();
  for (int i = 0; i < 5; i++) {
    pinMode(Optics[i], INPUT);
  }
  ServoParking();

}

void loop()  {
  currentTime = millis();
  if (currentTime >= (loopTime + 5)) { // проверяем каждые 5мс

    //     int  val = analogRead(0);     // считываем значение
    //  Serial.println(val);
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера
    if ((!encoder_A) && (encoder_A_prev)) {  // если состояние изменилось с положительного к нулю

      //Вращение влево
      if (encoder_B) {
        if (MenuFlag == 0) {
          (Menu <= 0 ) ? Menu = 2 : Menu--; // Перемещение курсора по главному меню назад
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink <= min_Drink ) ? Drink = max_Drink : Drink--; // Уменьшаем кол-во милилитров в рюмку
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (DrinkCount >= max_DrinkCount ) ? DrinkCount = 1 : DrinkCount++; // Влево увечичиваем рюмки для ручного режима
          oled_manual(DrinkCount, Drink);
        }
        //Вращение вправо
      } else {
        if (MenuFlag == 0) {
          (Menu >= 2 ) ? Menu = 0 : Menu++; // Перемещение курсора по главному меню вперед.
          oled_menu(Menu);
        } else if (MenuFlag == 1) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_auto(Drink);
        } else if (MenuFlag == 2) {
          (Drink >= max_Drink ) ? Drink = min_Drink : Drink++;
          oled_manual(DrinkCount, Drink);
        }
      }

    }

    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла

    int encoder_sw = digitalRead(pin_SW);
    if  (encoder_sw == 0 && encoder_sw != encoder_sw_prew)  { // Нажата кнопка

      int pause_sw = 0;
      boolean promivka = false;
      while (digitalRead(pin_SW) == 0) { // Держим кнопку. Считаем сколько времени прошло...
        delay(100);
        pause_sw++;
        if (pause_sw > 20 && Menu != 2 ) break;

        if (pause_sw > 20 && Menu == 2 && promivka == false) { // Если пункт меню промывка и держим кнопку больше 2 секунд.
          promivka = true;
          pump_enable(); // Включаем насос
          lcd.setCursor(0, 0);
      lcd.print("П Р О М Ы В К А");
          lcd.setCursor(2, 0);
      lcd.print(">>>>>>>>>>>>");
        }
      }

      //После отпускания кнопки , обрабатываем
      if (promivka == true) { //Отпустили кнопку. Если включена промывка, выключаем насос и возвращаемся в главное меню
        promivka = false;
        pump_disable() ; //Выключаем насос
        oled_menu(2);

      } else {
        //Обработка всех нажатий кнопки
        if (Menu == 0 && MenuFlag == 0 &&  pause_sw < 10) { //Нажатие кнопки меню авто
          MenuFlag = 1;
          oled_auto(Drink);
        } else if (MenuFlag == 1 && pause_sw > 20) { //Выход из меню авто в главное
          MenuFlag = 0;
          oled_menu(0);
        } else if (MenuFlag == 1 ) { //Начинается автоматический разлив
          Serial.println("Начало автоматического разлива");
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          byte drink_count = 0;
          for (int y = 0; y < max_DrinkCount; y++) {
            if (analogRead(Optics[y]) > Optics_porog[y] ) {
              strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
              strip.show();
              ServoNaliv(y); // Перемещяемся к рюмке
              pump_timer(Drink); // Налив.
              strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
              strip.show();
              drink_count++;
            }
          }
          if (drink_count > 0) {
            oled_nalito(MenuFlag, drink_count );
            ServoParking();
            delay(1000);
//           Tost();
            CvetoMuzik();
            oled_auto(Drink);
          } else {
            lcd.setCursor(7, 1);
            lcd.print("НЕТ РЮМОК!");
            delay(2000);
            oled_auto(Drink);

          }
        } else if (Menu == 1 && MenuFlag == 0 &&  pause_sw < 10) { // Нажатие меню ручное
          MenuFlag = 2;
          oled_manual(DrinkCount, Drink);
        } else if (MenuFlag == 2 && pause_sw > 20) { //Выход из меню ручное в главное
          MenuFlag = 0;
          oled_menu(1);
        } else if (MenuFlag == 2 ) { //Начинается ручной разлив
          //  Serial.println("Начало ручного разлива " + String(DrinkCount));
          oled_naliv(MenuFlag); // Выводим на экран наливаем ...
          for (int y = 0; y < DrinkCount; y++) {
            strip.setPixelColor(y, strip.Color(255, 0, 0)); // Подствечиваем красным цветом
            strip.show();
            ServoNaliv(y); // Перемещяемся к рюмке
            pump_timer(Drink); // Налив.
            strip.setPixelColor(y, strip.Color(0, 255, 0)); // Подствечиваем зеленым , налито.
            strip.show();
          }
          oled_nalito(MenuFlag, DrinkCount );
          ServoParking();
          //Tost();
          CvetoMuzik();
          oled_manual(DrinkCount, Drink);
        }
      }
    }

    if (currentTime >= (ledTime + 300)) {
      //Опрашиваем оптопары ... Если рюмка поставлена , светодиод светится синим, нет ничего - не светится
      for (int i = 0; i < max_DrinkCount; i++) {
        
        int val = analogRead(Optics[i]);     // считываем значение
        Serial.println(val);
        if (val > Optics_porog[i]) {
          strip.setPixelColor(i, strip.Color(0, 0, 255));
        } else {
          strip.setPixelColor(i, strip.Color(0, 0, 0));
        }
    //    delay(20);

      }
      strip.show();
      ledTime = currentTime;
    }
    encoder_sw_prew = encoder_sw;
    loopTime = currentTime;

  }
}
/*
Скетч использует 13484 байт (43%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 974 байт (47%) динамической памяти, оставляя 1074 байт для локальных переменных. Максимум: 2048 байт.
*/

stpavel
Онлайн
Зарегистрирован: 09.10.2018

Forthomo пишет:

Помоги менюху написать для LCD1602 заготовку прилагаю , блок ТОСТ еще не готов.

 


void oled_menu(byte Menu) {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("НАЛИВАТОР+");
  lcd.setCursor(0, 1);
  lcd.print(F(">"));
  lcd.setCursor(15, 1);
  lcd.print(F("<"));
  switch (Menu) {
    case 0:
      lcd.setCursor(6, 1);
      lcd.print(F("АВТО"));
      break;
    case 1:
      lcd.setCursor(2, 1);
      lcd.print(F("РУЧНОЙ РЕЖИМ"));
      break;
    case 2:
      lcd.setCursor(4, 1);
      lcd.print(F("ПРОМЫВКА"));
      break;
  }
}
Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

Павел, спасибо! Выкладываю скетч где можно посмотреть Экраны LCD:

#include <LCD_1602_RUS.h>
// https://codeload.github.com/ssilver2007/LCD_1602_RUS/zip/master
LCD_1602_RUS lcd(0x27, 16, 2);

int mll=25;
int temp=3;

void setup()
{
  lcd.init();  // initialize the lcd
  lcd.backlight();
}
 
void loop(){
	// меню авто
	lcd.setCursor(3, 0);
	lcd.print("HАЛИВАТОР");
	lcd.setCursor(2, 1);
	lcd.print("<   АВТО   >");
	delay(3000);
	lcd.clear();
	// меню ручной
	lcd.setCursor(3, 0);
	lcd.print("HАЛИВАТОР");
	lcd.setCursor(2, 1);	
	lcd.print("<  РУЧНОЙ  >");
	delay(3000);
	lcd.clear();
	// меню промывка
	lcd.setCursor(3, 0);
	lcd.print("HАЛИВАТОР");
	lcd.setCursor(2, 1);	
	lcd.print("< ПРОМЫВКА >");
	delay(3000);
	lcd.clear();
	// промывка
	lcd.setCursor(3, 0);
	lcd.print("ПРОМЫВКА");
	lcd.setCursor(4, 1);	
	lcd.print(">>>>>>");
	delay(3000);
	lcd.clear();
	//
    lcd.setCursor(0, 0);
    lcd.print("HАЛИТЬ ПО");
    lcd.setCursor(10, 0);
    lcd.print(mll); //ПЕРЕМЕННАЯ
    lcd.setCursor(13, 0);
    lcd.print("мЛ?");
    lcd.setCursor(1, 1);
    lcd.print("ПО ЧУТЬ - ЧУТЬ");
	delay(3000);
	lcd.clear();
	// итог

	
	//АВТОНАЛИВ
	lcd.setCursor(3, 0);
	lcd.print("АВТОНАЛИВ");
	lcd.setCursor(0, 1);
	lcd.print("ПО");
	lcd.setCursor(3, 1);
    lcd.print(mll); //ПЕРЕМЕННАЯ
    lcd.setCursor(6, 1);
    lcd.print("мЛ В РЮМКУ");
	delay(3000);
	lcd.clear();
	
	
	// ручной налив
    lcd.setCursor(0, 0);
    lcd.print("HАЛИВАЮ ПО");
    lcd.setCursor(11, 0);
    lcd.print(mll); //ПЕРЕМЕННАЯ
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
    lcd.setCursor(3, 1);
    lcd.print("В");
    lcd.setCursor(5, 1);
    lcd.print(temp);//ПЕРЕМЕННАЯ
    lcd.setCursor(7, 1);
    lcd.print("РЮМ");
    lcd.setCursor(10, 1);
    lcd.print("КИ");//ПЕРЕМЕННАЯ "ОК"   "КУ"
	delay(3000);
	lcd.clear();
	// итог
    lcd.setCursor(0, 0);
    lcd.print("HАЛИТО  ПО");
    lcd.setCursor(11, 0);
    lcd.print(mll); //ПЕРЕМЕННАЯ
    lcd.setCursor(14, 0);
    lcd.print("мЛ");
    lcd.setCursor(3, 1);
    lcd.print("В");
    lcd.setCursor(5, 1);
    lcd.print(temp);//ПЕРЕМЕННАЯ
    lcd.setCursor(7, 1);
    lcd.print("РЮМ");
    lcd.setCursor(10, 1);
    lcd.print("КИ");//ПЕРЕМЕННАЯ 5 - "ОК", 1 - "КУ", 2..4 -"КИ"	
	delay(3000);
	lcd.clear();
	//
	
/*  void Tost() {
  randomSeed(currentTime);
   Рандом - 1
  switch (random(18)) { // 0...17  
  */
  //case 0:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА ВСТРЕЧУ!");
  delay(3000);
  lcd.clear();
  //case 1:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА КРАСОТУ!");   
  delay(3000);
  lcd.clear();
  //case 2:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");//
  lcd.setCursor(3, 1);
  lcd.print(L"ЗА ДРУЖБУ!");    
  delay(3000);
  lcd.clear();
  //case 3:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА БРАТСТВО!");    
  delay(3000);
  lcd.clear();
  //case 4:
  lcd.setCursor(5, 0);
  lcd.print(L"НУ, ЗА");
  lcd.setCursor(1, 1);
  lcd.print(L"СПРАВЕДЛИВОСТЬ!");
  delay(3000);
  lcd.clear();
  //case 5:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(3, 1);
  lcd.print(L"ЗА РЫБАЛКУ!");
  delay(3000);
  lcd.clear();
  //case 6:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА ИСКУССТВО!");
  delay(3000);
  lcd.clear();
  //case 7:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(3, 1);
  lcd.print(L"ЗА РАЗУМ!");
  delay(3000);
  lcd.clear();
  //case 8:
  lcd.setCursor(5, 0);
  lcd.print(L"НУ, ЗА");
  lcd.setCursor(0, 1);
  lcd.print(L"ИСТИННЫХ ЖЕНЩИН!!");
  delay(3000);
  lcd.clear();
  //case 9:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА ПОНИМАНИЕ!");
  delay(3000);
  lcd.clear();  
  //case 10:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(2, 1);
  lcd.print(L"ЗА ЕДИНЕНИЕ!");
  delay(3000);
  lcd.clear();
  //case 11:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(3, 1);
  lcd.print(L"ЗА ПОБЕДУ!");
  delay(3000);
  lcd.clear();  
  //case 12:
  lcd.setCursor(7, 0);
  lcd.print(L"НУ,");
  lcd.setCursor(3, 1);
  lcd.print(L"ЗА РОДИНУ!");
  delay(3000);
  lcd.clear(); 
  //case 13:
  lcd.setCursor(0, 0);
  lcd.print(L"НУ, ЧТОБ ГОЛОВА");
  lcd.setCursor(2, 1);
  lcd.print(L"НЕ ТРЕЩАЛА!");
  delay(3000);
  lcd.clear(); 
  //case 14:
  lcd.setCursor(0, 0);
  lcd.print("НУ, ЗА  СОЛИДНОЕ");//НУ,
  lcd.setCursor(0, 1);
  lcd.print("МУЖСКОЕ МОЛЧАНИЕ!");
  delay(3000);
  lcd.clear();
  //case 15:
  lcd.setCursor(0, 0);
  lcd.print(L"НУ, ЧТОБ МОРЩИЛО");
  lcd.setCursor(3, 1);
  lcd.print(L"НАС МЕНЬШЕ");
  delay(3000);
  lcd.clear();    
  //case 16:
  lcd.setCursor(0, 0);
  lcd.print(L"НУ,ЧТОБ В СТОРО-");
  lcd.setCursor(0, 1);
  lcd.print(L"НУ НЕ  ВИЛЬНУЛО!");
  delay(3000);
  lcd.clear();
  //case 17:
  lcd.setCursor(2, 0);
  lcd.print("НУ ВЫ БЛИН");
  lcd.setCursor(5, 1);
  lcd.print("ДАЁТЕ!");  
  delay(3000);
  lcd.clear();

}
/*
Скетч использует 8682 байт (28%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1171 байт (57%) динамической памяти, оставляя 877 байт для локальных переменных.
Максимум: 2048 байт.
*/

блок с тостами

  void Tost() {
  randomSeed(currentTime);
//Рандом - 1
  switch (random(18)) { // 0...17
	case 0: //ЗА ВСТРЕЧУ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА ВСТРЕЧУ!");
		mp3_play (2);  // Проигрываем "mp3/0002.mp3"
		delay(100);
    case 1: //ЗА КРАСОТУ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА КРАСОТУ!");   
		delay(4000);
		mp3_play (3);  // Проигрываем "mp3/0003.mp3"
		delay(100);
	case 2: //"ЗА ДРУЖБУ!"
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");//
		lcd.setCursor(3, 1);
		lcd.print(L"ЗА ДРУЖБУ!");  
		mp3_play (4);  // Проигрываем "mp3/0004.mp3"
		delay(100);
	case 3: //"ЗА БРАТСТВО!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА БРАТСТВО!");   
		mp3_play (5);  // Проигрываем "mp3/0005.mp3"
		delay(100);
	case 4: //ЗА СПРАВЕДЛИВОСТЬ!
		lcd.setCursor(5, 0);
		lcd.print(L"НУ, ЗА");
		lcd.setCursor(1, 1);
		lcd.print(L"СПРАВЕДЛИВОСТЬ!");
		mp3_play (6);  // Проигрываем "mp3/0006.mp3"11
		delay(100);
    case 5: //ЗА РЫБАЛКУ!
	lcd.setCursor(7, 0);
	lcd.print(L"НУ,");
	lcd.setCursor(3, 1);
	lcd.print(L"ЗА РЫБАЛКУ!");
		mp3_play (7);  // Проигрываем "mp3/0007.mp3"
		delay(100);
	case 6: //ЗА ИСКУССТВО!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА ИСКУССТВО!");
		mp3_play (8);  // Проигрываем "mp3/0008.mp3"
		delay(100);
	case 7: //ЗА РАЗУМ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(3, 1);
		lcd.print(L"ЗА РАЗУМ!");
		mp3_play (9);  // Проигрываем "mp3/0009.mp3"
		delay(100);
    break; 
	case 8: //ЗА ИСТИННЫХ ЖЕНЩИН!
		lcd.setCursor(5, 0);
		lcd.print(L"НУ, ЗА");
		lcd.setCursor(0, 1);
		lcd.print(L"ИСТИННЫХ ЖЕНЩИН!!");
		mp3_play (10);  // Проигрываем "mp3/0010.mp3"
		delay(100);
    break;
	case 9: //ЗА ПОНИМАНИЕ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА ПОНИМАНИЕ!");
		mp3_play (11);  // Проигрываем "mp3/0011.mp3"
		delay(100);
    break;
	case 10: //ЗА ЕДИНЕНИЕ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(2, 1);
		lcd.print(L"ЗА ЕДИНЕНИЕ!");
		mp3_play (13);  // Проигрываем "mp3/0013.mp3"
		delay(100);
    break;
	case 11: //ЗА ПОБЕДУ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(3, 1);
		lcd.print(L"ЗА ПОБЕДУ!");
		mp3_play (16);  // Проигрываем "mp3/0016.mp3"
		delay(100);
    break;
	case 12: //ЗА РОДИНУ!
		lcd.setCursor(7, 0);
		lcd.print(L"НУ,");
		lcd.setCursor(3, 1);
		lcd.print(L"ЗА РОДИНУ!");
		mp3_play (21);  // Проигрываем "mp3/0021.mp3"
		delay(100);
    break;
	case 13: //ЧТОБ ГОЛОВА НЕ ТРЕЩАЛА!
		lcd.setCursor(0, 0);
		lcd.print(L"НУ, ЧТОБ ГОЛОВА");
		lcd.setCursor(2, 1);
		lcd.print(L"НЕ ТРЕЩАЛА!");
		mp3_play (17);  // Проигрываем "mp3/0017.mp3"
		delay(100);
    break;
	case 14: //ЗА СОЛИДНОЕ МУЖСКОЕ МОЛЧАНИЕ
		lcd.setCursor(0, 0);
		lcd.print("НУ, ЗА  СОЛИДНОЕ");//НУ,
		lcd.setCursor(0, 1);
		lcd.print("МУЖСКОЕ МОЛЧАНИЕ!");
		mp3_play (12);  // Проигрываем "mp3/0012.mp3"
		delay(100);
    break;
	case 15: //ЧТОБ МОРЩИЛО НАС МЕНЬШЕ!
		lcd.setCursor(0, 0);
		lcd.print(L"НУ,ЧТОБЫ МОРЩИЛО");
		lcd.setCursor(3, 1);
		lcd.print(L"НАС МЕНЬШЕ ЧЕМ");
		mp3_play (18);  // Проигрываем "mp3/0018.mp3"
		delay(100);
    break;
	case 16: //ЧТОБ В СТОРОНУ НЕ ВИЛЬНУЛО!
		lcd.setCursor(0, 0);
		lcd.print(L"НУ,ЧТОБ В СТОРО-");
		lcd.setCursor(0, 1);
		lcd.print(L"НУ НЕ  ВИЛЬНУЛО!");
		mp3_play (19);  // Проигрываем "mp3/0019.mp3"
		delay(100);
    break; 
	case 17: //НУ ВЫ БЛИН ДАЁТЕ!
		lcd.setCursor(2, 0);
		lcd.print("НУ ВЫ БЛИН");
		lcd.setCursor(5, 1);
		lcd.print("ДАЁТЕ!");
		mp3_play (20);  // Проигрываем "mp3/0020.mp3"
		delay(100);	
    break;		
  }
  mp3_stop();
  lcd.clear();

}

 

RW3
RW3 аватар
Offline
Зарегистрирован: 07.08.2019

что то тема заглохла..... Может схемы хватает? кто нибудь полностью привязал скетч к железу?

stpavel
Онлайн
Зарегистрирован: 09.10.2018

RW3 пишет:

что то тема заглохла..... Может схемы хватает? кто нибудь полностью привязал скетч к железу?

А какие проблемы привязки скетча к железу ? Там же все расписано к какому пину что соеденять. 

RW3
RW3 аватар
Offline
Зарегистрирован: 07.08.2019

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

aleks_raichel
Offline
Зарегистрирован: 27.08.2019

День добрый. А не перерабатывали скетч под Вашу схему?

Forthomo
Forthomo аватар
Онлайн
Зарегистрирован: 10.04.2019

RW3 пишет:

что то тема заглохла..... Может схемы хватает? кто нибудь полностью привязал скетч к железу?

Замечания по предоставленной схеме:

питания от внутреннего стабилизатора не хватит для запитки DFPlayer и ленты.

DFPlayer -  подкдючение динамика SPK1(6)  SPK2 (8) (земля не используется).

паралельно конденсатору помпа включить диод (чтобы не палить контакты реле и если используется силовой ключ не спалить мосфет).

Описание в 182 сообщении.

То же жду посылку с Али с МП3, все остальное работает, осталось в культурный корпус запихнуть.

Сейчас буду собирать с ЛСД1602 дисплеем, внутренней ёмкостью на 500мЛ и тонким поворачивающимся краником.