//Скетч для проверки преобразователя ШИМ-сигнала с Ардуино в напряжение +-10В #include <LiquidCrystal_I2C.h> //библиотеки работы с LCD через I2C #include <Wire.h> //Не забудь шунтировать выход от кнопок резистором 10 КОм const int BtDownPin = 5; //пин кнопки уменьшить. const int BtUpPin = 6; //пин кнопки увеличить //пин ШИМ-сигнала отвечающий за положительную часть сигнала (0 - +10В) const int pwmPinPositive = 3; //пин ШИМ-сигнала отвечающий за отрицательную часть сигнала (0 - -10В) const int pwmPinNegative = 9; //пины модуля I2C LCD-дисплея : //SDA - A4 //SCL - A5 //питание от шилда boolean LastButtonDown = LOW; //предыдущее состояние кнопки ВВЕРХ boolean CurrentButtonDown = LOW; //текущее состояние кнопки ВВЕРХ boolean LastButtonUp = LOW; // --- ВНИЗ boolean CurrentButtonUp = LOW; // --- ВНИЗ boolean FlagUpLoop = true; //были ли мы в цикле нажатия кнопки ВВЕРХ boolean FlagDownLoop = true; //были ли мы в цикле нажатия кнопки ВНИЗ boolean FlagUpHold = true; //были ли мы в цикле удержания кнопки ВВЕРХ boolean FlagDownHold = true; //были ли мы в цикле удержания кнопки ВНИЗ //нужна при нажатии и удерживании кнопки ВВЕРХ unsigned long ButtonHoldTimerUp = 0; //нужна при нажатии и удерживании кнопки ВНИЗ unsigned long ButtonHoldTimerDown = 0; //по прошествии этого времени кнопка ВВЕРХ или ВНИЗ //перейдет в режим удержания, мс const long ButtonHoldIncTime = 500; float pwmValue = 0; //скважность сигнала float VoltageCalculated = 10; //расчетное напряжение на выходе float VoltageFactor = 10; //коэффициент перевода скважности ШИМ-сигнала в напряжение на выходе с //задатчика напряжения (расчетное!!! реальное задается задатчиком с //помощью резисторов). По сути это максимальное напряжение, которое вы //хотите получить на выходе с задатчика при максимальном сигнале (скважности) //с выходного пина. Здесь это 10 вольт при 255 скважности. LiquidCrystal_I2C lcd(0x27,16,2); // Задаем адрес и размерность дисплея. void setup() //******************************************************** { pinMode (BtDownPin, INPUT) ; pinMode (BtUpPin, INPUT) ; pinMode (pwmPinPositive, OUTPUT); pinMode (pwmPinNegative, OUTPUT); lcd.init(); //Инициализация lcd lcd.backlight(); //Включаем подсветку lcd.setCursor(0,0); //рисуем первую строчку lcd.print(" PWM to Voltage "); lcd.setCursor(0,1); //рисуем вторую строчку lcd.print(" Test "); delay(2000); //Пауза в мс. } void loop() //**************************************************** { lcd.setCursor(0,0); //прописываем первую строку lcd.print("DUTY(pin"); if (pwmValue >= 0) { analogWrite(pwmPinPositive, pwmValue); lcd.print(pwmPinPositive); } else { analogWrite(pwmPinNegative, (-1)*pwmValue); lcd.print(pwmPinNegative); } lcd.print(")="); lcd.print(pwmValue, 0); lcd.print(" "); VoltageCalculated = VoltageFactor * pwmValue / 255; lcd.setCursor(0,1); //рисуем вторую строчку lcd.print("VC="); lcd.print(VoltageCalculated); lcd.print(" "); //******************* Нажата кнопка Увеличить ************************** CurrentButtonUp = debounce(LastButtonUp, BtUpPin); ButtonPlus(CurrentButtonUp); //функция реакции на нажатие кнопки Увеличить LastButtonUp = CurrentButtonUp; //обновляем текущее значение кнопки //******************* Нажата кнопка Уменьшить ************************** CurrentButtonDown = debounce(LastButtonDown, BtDownPin); ButtonMinus(CurrentButtonDown); //функция реакции на нажатие кнопки Уменьшить LastButtonDown = CurrentButtonDown; //обновляем текущее значение кнопки } //void loop() //********************** ФУНКЦИИ ********************************* //********* Функция кнопки Больше, Увеличить, Плюс и т.п. ************* void ButtonPlus(boolean BtState) //BtState - состояние кнопки (нажата-отжата) { if(BtState == HIGH) //кнопка нажата { if(FlagUpHold == true) //отсечка времени удержания кнопки { ButtonHoldTimerUp = millis(); FlagUpHold = false; } if(millis() - ButtonHoldTimerUp > ButtonHoldIncTime) //сначала однократное нажатие, но если держать кнопку более //ButtonHoldIncTime, она переходит в режим удержания { pwmValue = pwmValue + Inc_Val_Calc(true); if(pwmValue > 255) { pwmValue = 255; } } if(FlagUpLoop == true) //однократное нажатие, даже если удерживать кнопку, //пока не прошло ButtonHoldIncTime { FlagUpLoop = false; pwmValue = pwmValue + Inc_Val_Calc(false); if(pwmValue > 255) { pwmValue = 255; } } } else //кнопка отжата { FlagUpLoop = true; FlagUpHold = true; } } //********* Функция кнопки Меньше, Уменьшить, Минус или т.п. ************* void ButtonMinus(boolean BtState) //BtState - состояние кнопки (нажата-отжата) { if(BtState == HIGH) //кнопка нажата { if(FlagDownHold == true) //отсечка времени удержания кнопки { ButtonHoldTimerDown = millis(); FlagDownHold = false; } if(millis() - ButtonHoldTimerDown > ButtonHoldIncTime) //сначала однократное нажатие, но если держать кнопку более //ButtonHoldIncTime, она переходит в режим удержания { pwmValue = pwmValue - Inc_Val_Calc(true); if(pwmValue > 255) { pwmValue = 255; } } if(FlagDownLoop == true) //однократное нажатие, даже если удерживать кнопку, //пока не прошло ButtonHoldIncTime { FlagDownLoop = false; pwmValue = pwmValue - Inc_Val_Calc(false); if(pwmValue > 255) { pwmValue = 255; } } } else //кнопка отжата { FlagDownLoop = true; FlagDownHold = true; } } //*************** Функция устранения дребезга контактов *********** boolean debounce(boolean last, int ButtonPinDebounce) { boolean current = digitalRead(ButtonPinDebounce); //считываем текущее состояние кнопки if(last != current) //если оно иное, чем предыдущее... { delay(50); //ждем 50 мс current = digitalRead(ButtonPinDebounce); //считываем состояние снова } return current; //возвращаем текущее состояние кнопки } //*************** Функция разгона приращения параметра ************ int Inc_Val_Calc(boolean IncTrigger) { static int count_inc = 0; //счетчик итераций if (IncTrigger == true) //пришел сигнал на разгон { count_inc = count_inc + 1; //играя этими числами, вы можете подстраивать разгон параметра под себя if (count_inc > 0 && count_inc <= 30) { return 1; } if (count_inc > 30 && count_inc <= 60) { return 2; } if (count_inc > 60) { return 5; } } else { count_inc = 0; return 1; //приращение по умолчанию } }