Created
October 1, 2017 17:23
-
-
Save enwi/b0e7557168d63f8f8a363cd6201aa850 to your computer and use it in GitHub Desktop.
Arduino code for the fan control of the modified power inverter: https://youtu.be/2shofvjHGbU
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/sleep.h> | |
#include <avr/wdt.h> | |
#include <OneWire.h> | |
#include <DallasTemperature.h> | |
// Function Prototype for wdt_init (place it in init3 section, before main executes to prevent perma-resetting) | |
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3"))); | |
void wdt_init(void) | |
{ | |
MCUSR = 0; | |
wdt_disable(); | |
return; | |
} | |
// All temperatures are calculated by 128 * temperature (degrees C) | |
const int16_t max_temperature = 7680; // temperature when fans are at max_fan_speed | |
const int16_t min_temperature = 5504;//4480; // temperature when fans turn on | |
const int16_t difference_temperature = 384; // min_temperature - difference_temperature when fans turn off (384 = 3 degrees C) | |
const uint8_t min_fan_speed = 10; | |
const uint8_t max_fan_speed = 200; | |
const uint8_t fan_pin = 6; | |
const uint8_t sensor_pin = 7; | |
int16_t current_temperature = 0; | |
uint8_t current_fan_speed = 0; | |
uint8_t new_fan_speed = 0; | |
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) | |
OneWire oneWire(sensor_pin); | |
// Pass our oneWire reference to Dallas Temperature. | |
DallasTemperature sensor(&oneWire); | |
DeviceAddress sensor_address; | |
void initWDT() | |
{ | |
wdt_reset(); | |
MCUSR &= ~(1<<WDRF); // clear WDRF | |
WDTCSR |= (1<<WDCE) | (1<<WDE); // enable WDTCSR change | |
WDTCSR = (1<<WDIE) | (1<<WDP2) | (1<<WDP1); // ~1 sec | |
} | |
uint8_t cSREG; | |
void gotoSleep() | |
{ | |
cSREG = SREG; // store SREG | |
cli(); // timed sequences follow | |
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // use deepest sleep mode | |
sleep_enable(); | |
MCUCR = (1<<BODS) | (1<<BODSE); // turn off the brown-out detector while sleeping | |
MCUCR = (1<<BODS); // BODS stays active for 3 cycles, sleep instruction must be executed while it's active | |
SREG = cSREG; // restore SREG, because we need interrupts now | |
sleep_cpu(); // go to sleep | |
sleep_disable(); // wake up here | |
initWDT(); // initialize WDT for sleep cycle | |
} | |
void saveEnergy() | |
{ | |
uint8_t oldSREG = SREG; // save SREG | |
cli(); | |
PRR |= 0x8D; // shut off TWI & Timer/Counter1 & SPI & ADC | |
ADCSRA = 0; // disable the ADC | |
ADCSRB &= ~(_BV(ACME)); | |
ACSR &= (1<<ACIE); // disable Analog Comparator interrupt to not trigger it in the next command | |
ACSR |= (1<<ACD); // disable Analog Comparator | |
DDRD &= ~ 0x7F; // set all pins as input except sensor pin | |
PORTD |= 0x7F; // turn internal pullup on except sensor pin | |
DDRB &= ~ 0xFF; // set all pins as input | |
PORTB |= 0xFF; // turn internal pullup on | |
DDRC &= ~ 0x3F; // set all pins as input except reset pin | |
PORTC |= 0x3F; // except reset pin where we do not want to enable pullup | |
DIDR0 = 0x3F; // disable ADC0D - ADC7D to save more energy, but bits 6 & 7 need to always be 0 | |
DIDR1 = 0x03; // enable AIN0D & AIN1D to disable digital input buffer of pins 6 & 7 | |
SREG = oldSREG; // restore SREG | |
} | |
void setup() | |
{ | |
//initWDT(); // initialize WDT for sleep cycle | |
saveEnergy(); // use as least energy as possible | |
Serial.begin(19200); // begin serial with a baudrate of 57600 | |
Serial.println("Inverter fan control"); | |
sensor.begin(); // initialize ds18b20 lib | |
while( !sensor.getAddress(sensor_address, 0) ) // try to get the address | |
{ | |
Serial.println("Failed to find sensor. Trying again after 1 second"); | |
gotoSleep(); | |
} | |
sensor.setResolution(sensor_address, 11); // set ds18b20 resolution to 11 bits | |
pinMode(fan_pin, OUTPUT); // set fan_pin as output | |
analogWrite(fan_pin, max_fan_speed); | |
delay(1000); | |
analogWrite(fan_pin, 0); | |
////OCR0A = 0; // set PWM to 0% duty cycle | |
////TCCR0A |= (1 << COM0A1) | (1 << WGM00); // clear output on compare match & set PWM phase correct mode | |
//TCCR0B |= (1 << WGM02) | (1 << CS00); // use OCR0A to compare & set prescaler to 1 to get a signal of around 31kHz (31372,549019607843137 Hz) | |
////TCCR0B |= (1 << WGM02) | (1 << CS01); // use OCR0A to compare & set prescaler to 8 to get a signal of around 4kHz (3921,568627450980392 Hz) | |
////TCCR0B |= (1 << WGM02) | (1 << CS01) | (1 << CS00); // use OCR0A to compare & set prescaler to 64 to get a signal of around 490 Hz (490,196078431372549 Hz) | |
////OCR2A = 0; | |
// set PWM for 50% duty cycle | |
////TCCR2A |= (1 << COM2A1); | |
// set none-inverting mode | |
////TCCR2A |= (1 << WGM21) | (1 << WGM20); | |
// set fast PWM Mode | |
////TCCR2B |= (1 << CS21); | |
} | |
void loop() | |
{ | |
Serial.flush(); | |
sensor.requestTemperatures(); // Send the command to get temperatures | |
//Serial.print("Current temp: "); | |
current_temperature = sensor.getTemp(sensor_address); // get the current raw temperature | |
Serial.println(float(current_temperature)/128); // print the temperature after conversion | |
if( current_temperature > min_temperature ) // if current temperature is bigger than minimal temperature to start the fan | |
{ | |
new_fan_speed = map(current_temperature, min_temperature - difference_temperature, max_temperature, min_fan_speed, max_fan_speed); // map the current temperature with it's defined max and min to a fan speed | |
if( current_fan_speed != new_fan_speed ) // only change the fan speed when it changed | |
{ | |
Serial.println("Turning fan on"); | |
analogWrite(fan_pin, new_fan_speed); // set the PWM register to the current fan speed | |
current_fan_speed = new_fan_speed; // set the new fan speed as current | |
} | |
} | |
else if( current_temperature < (min_temperature - difference_temperature) && current_fan_speed ) // if tmeperature is smaller than min_temperature - 0.5 degrees | |
{ | |
Serial.println("Turning fan off"); | |
current_fan_speed = 0; // set current fan speed as 0 to turn it off | |
analogWrite(fan_pin, current_fan_speed); // set the PWM register to the current fan speed | |
} | |
Serial.flush(); | |
//gotoSleep(); // sleep for 1 second to save some energy | |
delay(1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment