ssr removed, pwm on pin 9 instead. durations length corrections

This commit is contained in:
Alexander Belov 2025-01-05 14:50:00 +07:00
parent f395491f45
commit 3aa9ab5cbd
4 changed files with 104 additions and 161 deletions

View File

@ -42,8 +42,6 @@ GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled;
#define SW 7
Encoder enc1(CLK, DT, SW, TYPE2);
// SSR pin configuration
const int ssrPin = 2;
const int triacPwm = 10;
const int activeBuzzerPin = 8;
@ -122,7 +120,6 @@ int failedReadingCount = 0;
#define PARTS 8
void setup() {
pinMode(ssrPin, OUTPUT);
pinMode(activeBuzzerPin, OUTPUT);
Serial.begin(9600);
@ -149,38 +146,3 @@ void setup() {
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)
}

View File

@ -26,10 +26,10 @@ void printPhases() {
oled.setCursor(0, 1);
oled.print(" ");
oled.setCursor(18, 1);
formatTime(totalElapsedTime, timeBuffer);
formatTime((long)totalElapsedTime, timeBuffer);
oled.print(timeBuffer);
oled.print(" / ");
formatTime(totalProcessTime, timeBuffer);
formatTime((long)totalProcessTime, timeBuffer);
oled.print(timeBuffer);
oled.print(" ");
@ -38,7 +38,7 @@ void printPhases() {
oled.invertText(true); // Invert text for the current phase
oled.setCursor(0, i + 2); // Set cursor to the row corresponding to the phase
long timeRemaining = (activeProfile.phases[i].duration * 60) - ((currentTime - phaseStartTime) / 1000);
long timeRemaining = ((long) activeProfile.phases[i].duration * 60) - ((currentTime - phaseStartTime) / 1000);
formatTime(timeRemaining, timeBuffer);
oled.print(i + 1);
oled.print(". ");
@ -58,7 +58,7 @@ void printPhases() {
oled.invertText(false); // Normal text for other phases
oled.setCursor(0, i + 2); // Set cursor to the row corresponding to the phase
formatTime(activeProfile.phases[i].duration * 60, timeBuffer);
formatTime((long)activeProfile.phases[i].duration * 60, timeBuffer);
oled.print(i + 1);
oled.print(". ");
oled.print(activeProfile.phases[i].temperature);
@ -84,13 +84,12 @@ void printPhases() {
if (failedReadingCount) {
oled.setCursor(0, 7);
oled.print(failedReadingCount);
oled.print(" (");
oled.print(failedReadingLastValue);
oled.print(") ");
oled.print("!");
}
oled.invertText(false); // Ensure text inversion is off after the loop
HandlePwmHeaterDisplay();
// oled.setCursor(110,7);
// sprintf(timeBuffer, "%3d", (int)(Output*100));
// oled.print(timeBuffer);
@ -129,4 +128,68 @@ void formatTime(long seconds, char* buffer) {
if (secs > 0) {
sprintf(buffer + strlen(buffer), "%ds", secs);
}
}
}
#define graphItems 30
// LP_TIMER(1000, HandlePwmHeaterDisplay);
void HandlePwmHeaterDisplay() {
static byte graphStates[graphItems];
static byte currentGraphItemNumber = 0;
if (inSelectionMode) {
Setpoint = 0;
return;
}
currentGraphItemNumber++;
if (currentGraphItemNumber >= graphItems) {
currentGraphItemNumber = 0;
}
byte graphHeight = 7;
byte currentAmount = Output==0 ? 0 : (Output-1)/99.0 * (graphHeight) + 1;
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++;
}
byte leftPosition = rightMargin - graphItems - 3*6 - 1;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(Output));
oled.invertText(true);
oled.print(timeBuffer);
oled.invertText(false);
leftPosition -= 6*3+2;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastD));
oled.print(timeBuffer);
leftPosition -= 6*3+2;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastI));
oled.print(timeBuffer);
leftPosition -= 6*3+2;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastP));
oled.print(timeBuffer);
}

View File

@ -3,121 +3,36 @@ LP_TIMER(1000, []() {
setPWMDutyCycle(power);
});
#define graphItems 32
LP_TIMER(1000, HandlePwmHeaterDisplay);
void HandlePwmHeaterDisplay() {
static byte graphStates[graphItems];
static byte currentGraphItemNumber = 0;
// Function to configure Timer1 for PWM with the specified window duration
void configureTimer1(unsigned long windowMillis) {
// Disable interrupts while configuring the timer
noInterrupts();
if (inSelectionMode) {
digitalWrite(ssrPin, LOW);
Setpoint = 0;
return;
}
// Reset Timer/Counter1 Control Registers
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
currentGraphItemNumber++;
if (currentGraphItemNumber >= graphItems) {
currentGraphItemNumber = 0;
}
// Set the prescaler to 256
TCCR1B |= (1 << CS12); // Set prescaler to 256
byte graphHeight = 8;
byte currentAmount = Output==0 ? 0 : (Output-1)/99.0 * (graphHeight) + 1;
// Calculate the top value for Timer1 based on the window duration
unsigned long ticks = (62500 * windowMillis) / 1000 / 2;
graphStates[currentGraphItemNumber] = currentAmount;
// Set the top value for Timer1 (ICR1) based on the calculated ticks
ICR1 = ticks - 1; // Subtract 1 because the counter starts at 0
byte rightMargin = 128;
byte topMargin = 63-graphHeight;
byte itemsDisplayed = 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
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);
}
// Set Phase Correct PWM mode with ICR1 as TOP
TCCR1B |= (1 << WGM13); // No WGM12
itemsDisplayed++;
}
byte leftPosition = 126-graphItems - 3*6;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(Output));
oled.invertText(true);
oled.print(timeBuffer);
oled.invertText(false);
leftPosition -= 6*3;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastD));
oled.print(timeBuffer);
leftPosition -= 6*3;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastI));
oled.print(timeBuffer);
leftPosition -= 6*3;
oled.setCursor(leftPosition, 7);
sprintf(timeBuffer, "%3d", (int)(regulator.lastP));
oled.print(timeBuffer);
// Enable interrupts again
interrupts();
}
// LP_TIMER(1000, HandleHeater);
void HandleHeater() {
static int currentPart = 0;
static bool states[PARTS];
if (inSelectionMode) {
digitalWrite(ssrPin, LOW);
Setpoint = 0;
return;
}
int current = Output/100 * PARTS;
int last = 0;
for (int i = 1; i < PARTS; i++) {
last += states[i] ? 1 : 0;
if (i) {
states[i-1] = states[i];
}
}
bool next = current >= last ? true : false;
if (Output < 1) next = false;
states[PARTS-1] = next;
oled.setCursor(128-6*PARTS, 7);
sprintf(timeBuffer, "%3d", (int)(Output));
char symbol;
for (int i = 0; i < PARTS; i++) {
int index = i - (PARTS - 3);
symbol = index < 0 ? ' ' : timeBuffer[index];
oled.invertText(states[i]);
oled.print(symbol);
oled.invertText(false);
}
if (temperatureSensorError) {
next = 0;
}
digitalWrite(ssrPin, next);
currentPart++;
if (currentPart >= PARTS) {
currentPart = 0;
}
#ifdef PlotValues
Serial.print(Setpoint);
Serial.print(",");
Serial.print(Input);
Serial.print(",");
Serial.print(Output);
Serial.println(",0,100");
#endif
void setPWMDutyCycle(uint8_t duty) {
OCR1B = (unsigned long)duty * ICR1 / 255; // Set the duty cycle for Pin 10 (OC1B)
}

View File

@ -14,6 +14,9 @@ void HandleExecution() {
regulator.getResultNow();
Output = regulator.output;
}
else {
Setpoint = 0;
}
if (isComplete && currentPhase >= activeProfile.numPhases && !finishTime) {
finishTime = currentTime;
@ -27,19 +30,19 @@ void getPhaseAndTemperature() {
long accumulatedTime = 0;
for (int i = 0; i < activeProfile.numPhases; i++) {
int phaseDuration = activeProfile.phases[i].duration * 60;
long phaseDuration = activeProfile.phases[i].duration * 60;
// Check for transition
if (i > 0) {
int previousTemp = activeProfile.phases[i - 1].temperature;
int targetTemp = activeProfile.phases[i].temperature;
int tempDiff = abs(targetTemp - previousTemp);
int transitionDuration = tempDiff * 60 * activeProfile.transitionMinutesPerDegree;
long transitionDuration = tempDiff * 60 * activeProfile.transitionMinutesPerDegree;
if (totalElapsedTime < accumulatedTime + transitionDuration) {
isInTransition = true;
currentPhase = i - 1; // Keep currentPhase as the previous phase
int timeInTransition = totalElapsedTime - accumulatedTime;
long timeInTransition = totalElapsedTime - accumulatedTime;
Setpoint = previousTemp + (double)timeInTransition / (60 * activeProfile.transitionMinutesPerDegree) * (targetTemp > previousTemp ? 1 : -1);
phaseStartTime = totalStartTime + accumulatedTime * 1000; // Set phase start time
return;
@ -49,7 +52,7 @@ void getPhaseAndTemperature() {
}
// Check if we're within the current phase
if (totalElapsedTime < accumulatedTime + phaseDuration) {
if (totalElapsedTime < (long) (accumulatedTime + phaseDuration)) {
isInTransition = false;
currentPhase = i;
Setpoint = activeProfile.phases[i].temperature;
@ -73,10 +76,10 @@ void calculateTotalTime() {
activeProfile = profiles[activeProfileIndex];
totalProcessTime = 0;
for (int i = 0; i < activeProfile.numPhases; i++) {
totalProcessTime += activeProfile.phases[i].duration * 60;
totalProcessTime += (long) activeProfile.phases[i].duration * 60;
if (i < activeProfile.numPhases - 1) {
int tempDiff = abs(activeProfile.phases[i + 1].temperature - activeProfile.phases[i].temperature);
totalProcessTime += tempDiff * 60 * activeProfile.transitionMinutesPerDegree;
long tempDiff = abs(activeProfile.phases[i + 1].temperature - activeProfile.phases[i].temperature);
totalProcessTime += (long) tempDiff * 60 * activeProfile.transitionMinutesPerDegree;
}
}
}