diff --git a/docs/ATMEGA32A.pdf b/docs/ATMEGA32A.pdf new file mode 100755 index 0000000..98be56a Binary files /dev/null and b/docs/ATMEGA32A.pdf differ diff --git a/docs/PWM-NOCTUA.pdf b/docs/PWM-NOCTUA.pdf new file mode 100755 index 0000000..1d1c594 Binary files /dev/null and b/docs/PWM-NOCTUA.pdf differ diff --git a/src/common.h b/src/common.h index 3378357..ba7ad6f 100644 --- a/src/common.h +++ b/src/common.h @@ -3,11 +3,15 @@ #include -#define BIT(n) (0x1U << (n)) -#define UNUSED(s) (void)(s) +#define BIT(n) (0x1U << (n)) +#define UNUSED(s) (void)(s) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(n, hi, lo) (MIN(hi, MAX(n, lo))) void Info(const char *fmt, ...); void Error(const char *fmt, ...); +double Clamp(double n, double upper, double lower); #include #define Sleep(ms) _delay_ms(ms) diff --git a/src/common/common.c b/src/common/common.c index 900f49b..132c9b5 100644 --- a/src/common/common.c +++ b/src/common/common.c @@ -1,6 +1,7 @@ #include "common.h" #include "bus/usart.h" #include +#include static void Puts(const char *str) { diff --git a/src/main.c b/src/main.c index ba655c8..4c669d7 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,11 @@ #include #include +// Minimum speed for Noctua fans is 20% +#define FAN_01_MIN_DUTY 255 / 100 * 20 +#define FAN_02_MIN_DUTY 255 / 100 * 20 +#define HEATER_MIN_DUTY 0 + // ADS1115 (ADC) // PCA9546 (Multiplexer TWI) // ATH20 (3x) @@ -26,6 +31,9 @@ static void SetPinDefaults(void); static void SetTWIChannel(int channel); +static void SetFan01Speed(int n); +static void SetFan02Speed(int n); +static void SetHeaterTemp(int n); int main(void) { @@ -39,29 +47,18 @@ int main(void) Info("Initializing..."); SetTWIChannel(0); - Sleep(500); + SetFan01Speed(51); + SetFan02Speed(51); + SetHeaterTemp(0); + + for (;;) { + Info("PING"); + Sleep(1000); + } return 0; } -static void SetPinDefaults(void) -{ - // Initialize Pin Outputs - // ====================== - - // PB0: MOSFET #1 (Peltier) - DDRB |= (1 << PB0); // Out - PORTB &= ~(1 << PB0); // Low - - // PB1: MOSFET #2 (Heating) - DDRB |= (1 << PB1); // Out - PORTB &= ~(1 << PB1); // Low - - // PB2: MOSFET #3 (Lights) - DDRB |= (1 << PB2); // Out - PORTB &= ~(1 << PB2); // Low -} - static void SetTWIChannel(int channel) { unsigned char crb; @@ -115,3 +112,107 @@ static void SetTWIChannel(int channel) Info("TWI channel was switched to %d.", channel); } + +static void SetPinDefaults(void) +{ + // Initialize Pin Outputs + // ====================== + + // PB0: MOSFET #1 (Peltier) + + DDRB |= BIT(PB0); // Out + PORTB &= ~BIT(PB0); // Low + + // PB1: MOSFET #2 (Heating) + + DDRB |= BIT(PB1); // Out + PORTB &= ~BIT(PB1); // Low + + // PB2: MOSFET #3 (Lights) + + DDRB |= BIT(PB2); // Out + PORTB &= ~BIT(PB2); // Low + + // PD4: PWM Peltier Hot Side + // PD5: PWM Peltier Cold Side + // PD7: PWM Heating + + DDRD |= BIT(PD4) | BIT(PD5) | BIT(PD7); + + // Fast mode, 8-bit, non-inverting, no prescaling + TCCR1A = BIT(WGM10) | BIT(COM1A1); + TCCR1B = BIT(WGM12) | BIT(CS10); + TCCR2 = BIT(WGM20) | BIT(WGM21) | BIT(COM21) | BIT(CS20); + + // PD4 OC1B (Timer/Counter1 Output CompareB Match Output) + OCR1A = 51; // Minimum speed for Noctua fans at 20% PWM + + // PD5 OC1A (Timer/Counter1 Output CompareA Match Output) + OCR1B = 51; // Minimum speed for Noctua fans at 20% PWM + + // PD7 OC2 (Timer/Counter2 Output Compare Match Output) + OCR2 = 0; // XXX: Set heater low to turn off? + + // TODO: Update documentation below from ATMega32A sheet... + // Had to skip the TCR0 timer and use TCR1 and TCR2 instead. + + // TCCR0 8-bit Timer/Counter Register + // 7 6 5 4 3 2 1 0 + // FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 + + // Waveform Generation Mode Bit + // Mode WGM01 WGM00 Counter Mode + // 0 0 0 Normal + // 1 0 1 PWM Phase Correct + // 2 1 0 CTC + // 3 1 1 PWM Fast + + // Compare Output Mode, Fast PWM Mode + // COM01 COM00 Description + // 0 0 Normal port operation, OC0 disconnected. + // 0 1 Reserved. + // 1 0 Clear OC0 on match, set OC0 at BOTTOM, (non-inverting mode). + // 1 1 Set OC0 on match, clear OC0 at BOTTOM, (inverting mode). + + // Compare Output Mode, Phase Correct PWM Mode + // COM01 COM00 Description + // 0 0 Normal port operation, OC0 disconnected. + // 0 1 Reserved. + // 1 0 Clear OC0 on match when up-counting, set when downcounting. + // 1 1 Set OC0 on match when up-counting, clear when downcounting. + + // Clock Select Bit + // CS02 CS01 CS00 Description + // 0 0 0 No clock source (Timer/Counter stopped). + // 0 0 1 clk I/O No prescaling + // 0 1 0 clk I/O /8 from prescaler + // 0 1 1 clk I/O /64 from prescaler + // 1 0 0 clk I/O /256 from prescaler + // 1 0 1 clk I/O /1024 from prescaler + // 1 1 0 External clock source on T0 pin. Clock on falling edge. + // 1 1 1 External clock source on T0 pin. Clock on rising edge. +} + +static void SetFan01Speed(int n) +{ + n = CLAMP(n, 0xFF, FAN_01_MIN_DUTY); + Info("Setting FAN01 to PWM %d.", n); + + OCR1B = (unsigned char) n; // PD4 +} + +static void SetFan02Speed(int n) +{ + n = CLAMP(n, 0xFF, FAN_02_MIN_DUTY); + Info("Setting FAN02 to PWM %d.", n); + + OCR1A = (unsigned char) n; // PD5 +} + +static void SetHeaterTemp(int n) +{ + n = CLAMP(n, 0xFF, HEATER_MIN_DUTY); + Info("Setting HEATER to PWM %d.", n); + + OCR2 = (unsigned char) n; // PD7 +}