ssr removed, pwm on pin 9 instead. durations length corrections
This commit is contained in:
parent
f395491f45
commit
3aa9ab5cbd
@ -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)
|
||||
}
|
||||
|
||||
79
output.ino
79
output.ino
@ -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);
|
||||
}
|
||||
|
||||
|
||||
131
t_heater.ino
131
t_heater.ino
@ -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)
|
||||
}
|
||||
|
||||
17
t_main.ino
17
t_main.ino
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user