From 4c650ecc48c6df7ccdcad8aed14aa0e4cfc46630 Mon Sep 17 00:00:00 2001 From: Aleksander Belov Date: Thu, 19 Dec 2024 23:20:33 +0700 Subject: [PATCH] PWM triac pin in addition --- README.md | 1 + hot_fermentation.ino | 46 ++++++++++++++++++++++++++++++++---- t_encoder.ino | 4 ++++ t_heater.ino | 56 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b795494..318b35d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ ## TODO +* развести плату \ No newline at end of file diff --git a/hot_fermentation.ino b/hot_fermentation.ino index adfa0b9..a54ddd8 100644 --- a/hot_fermentation.ino +++ b/hot_fermentation.ino @@ -25,10 +25,7 @@ #ifdef TempSensorDallas #include #include - // Data wire is plugged into port 2 on the Arduino #define ONE_WIRE_BUS 9 - - // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. @@ -47,6 +44,7 @@ Encoder enc1(CLK, DT, SW, TYPE2); // SSR pin configuration const int ssrPin = 2; +const int triacPwm = 10; const int activeBuzzerPin = 8; // Profile structure definition @@ -65,13 +63,13 @@ struct Profile { // Profiles definition Profile profiles[] = { {"Chickpeas", 1, {{46, 120}, {55, 60}, {65, 150}, {70, 60}, {90, 105}}, 5}, + {"Chickpeas long", 1, {{46, 120}, {55, 120}, {65, 120}, {72, 240}, {85, 300}}, 5}, {"Lentils", 3, {{46, 120}, {53, 120}, {65, 180}, {72, 90}, {90, 15}}, 5}, {"Gradual", 10, {{46, 120}, {90, 30}}, 2}, {"Long gradual", 15, {{46, 120}, {80, 60}, {90, 15}}, 3}, {"Wheat", 1, {{46, 120}, {53, 40}, {65, 40}, {72, 40}, {85, 40}}, 5}, {"Amazake", 1, {{51, 480}}, 1}, {"SV", 0, {{46, 45}}, 1}, - {"Tempeh magic", 1, {{46, 300}, {55, 180}, {72, 20}, {90, 15}}, 4}, // {"Yoghurt maker", 0, {{40, 300}, {40, 300}, {30, 300}}, 3}, // {"TEST", 0, {{46, 1}}, 1}, }; @@ -92,7 +90,7 @@ bool inSelectionMode = true; #include "GyverPID.h" double Setpoint, Input, Output; -GyverPID regulator(25, 0, 0, 1000); +GyverPID regulator(50, 1, 5, 1000); bool temperatureSensorError = false; @@ -133,6 +131,10 @@ void setup() { regulator.setLimits(0, 100); // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255 regulator.setpoint = 0; + pinMode(triacPwm, OUTPUT); + configureTimer1(1000); + setPWMDutyCycle(0); + #ifdef TempSensorDallas sensors.begin(); DeviceAddress tempDeviceAddress; @@ -146,3 +148,37 @@ void loop() { Looper.loop(); } + +// Function to configure Timer1 for PWM with the specified window duration +void configureTimer1(unsigned long windowMillis) { + // Disable interrupts while configuring the timer + noInterrupts(); + + // Reset Timer/Counter1 Control Registers + TCCR1A = 0; + TCCR1B = 0; + TCNT1 = 0; + + // Set the prescaler to 256 + TCCR1B |= (1 << CS12); // Set prescaler to 256 + + // Calculate the top value for Timer1 based on the window duration + unsigned long ticks = (62500 * windowMillis) / 1000 / 2; + + // Set the top value for Timer1 (ICR1) based on the calculated ticks + ICR1 = ticks - 1; // Subtract 1 because the counter starts at 0 + + // Configure Timer1 for Phase Correct PWM with ICR1 as TOP + // Enable non-inverted PWM on OC1B (Pin 10) + TCCR1A = (1 << WGM11) | (1 << COM1B1); // Only configure OC1B for PWM + + // Set Phase Correct PWM mode with ICR1 as TOP + TCCR1B |= (1 << WGM13); // No WGM12 + + // Enable interrupts again + interrupts(); +} + +void setPWMDutyCycle(uint8_t duty) { + OCR1B = (unsigned long)duty * ICR1 / 255; // Set the duty cycle for Pin 10 (OC1B) +} diff --git a/t_encoder.ino b/t_encoder.ino index 24ca636..a303cc8 100644 --- a/t_encoder.ino +++ b/t_encoder.ino @@ -30,6 +30,10 @@ void handleExecutionSelection() { } void handleProfileSelection() { + if (Setpoint > 0) { + Setpoint = 0; + } + if (!isClick && !isLeft && !isRight) { return; } diff --git a/t_heater.ino b/t_heater.ino index 40a8a91..bece136 100644 --- a/t_heater.ino +++ b/t_heater.ino @@ -1,10 +1,64 @@ -LP_TIMER(500, HandleHeater); +LP_TIMER(1000, []() { + int power = Output * 255 / 100; + setPWMDutyCycle(power); +}); + +#define graphItems 32 +LP_TIMER(1000, HandlePwmHeaterDisplay); +void HandlePwmHeaterDisplay() { + static byte graphStates[graphItems]; + static byte currentGraphItemNumber = 0; + + if (inSelectionMode) { + digitalWrite(ssrPin, LOW); + Setpoint = 0; + return; + } + + currentGraphItemNumber++; + if (currentGraphItemNumber >= graphItems) { + currentGraphItemNumber = 0; + } + + byte graphHeight = 10; + byte currentAmount = Output==0 ? 0 : (Output-1)/99.0 * (graphHeight) + 1; + Serial.println(currentAmount); + + graphStates[currentGraphItemNumber] = currentAmount; + + byte rightMargin = 128; + byte topMargin = 63-graphHeight; + byte itemsDisplayed = 0; + + while (itemsDisplayed < graphItems) { + int currentItemN = currentGraphItemNumber - itemsDisplayed; + if (currentItemN < 0) { + currentItemN += graphItems; + } + byte CurrentItemValue = graphStates[currentItemN]; + oled.fastLineV(rightMargin - graphItems + itemsDisplayed, topMargin, topMargin+graphHeight-CurrentItemValue+1, 0); + if (CurrentItemValue) { + oled.fastLineV(rightMargin - graphItems + itemsDisplayed, topMargin+graphHeight-CurrentItemValue+1, topMargin+graphHeight, 1); + } + + itemsDisplayed++; + } + + oled.setCursor(126-graphItems - 2*8, 7); + sprintf(timeBuffer, "%3d", (int)(Output)); + oled.invertText(true); + oled.print(timeBuffer); + oled.invertText(false); +} + +// LP_TIMER(1000, HandleHeater); void HandleHeater() { static int currentPart = 0; static bool states[PARTS]; if (inSelectionMode) { digitalWrite(ssrPin, LOW); + Setpoint = 0; return; }