Skip to content

Instantly share code, notes, and snippets.

@snilard
Created January 28, 2014 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snilard/8677343 to your computer and use it in GitHub Desktop.
Save snilard/8677343 to your computer and use it in GitHub Desktop.
Ovládací SW k vyhřívaným vložkám do bot.
//#define F_CPU 1000000UL
//----- Include Files ---------------------------------------------------------
#include <avr/io.h> // include I/O definitions (port names, pin names, etc)
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <util/delay.h>
#include <util/delay_basic.h>
//----- Begin Code ------------------------------------------------------------
// dělička 39 kOhm + 10kOhm
// napětí * 20,4 = voltage
#define LED1 PB0
#define LED2 PB2
#define WIRE PB1
#define VOLT_PIN PB3
#define INTE_PIN PB4
#define PWM_MAX 128
#define PWM_CEIL 120
#define INTENSITY_MIN 120
#define INTENSITY_MAX 240
#define INTENSITY_STEPS (INTENSITY_MAX - INTENSITY_MIN)
#define WANTED_MIN (60*60)
#define WANTED_MAX (140*140)
#define WANTED_STEPS (WANTED_MAX - WANTED_MIN)
#define LOW_VOLTAGE 137 // 6,7 V
#define WARNING_VOLTAGE 151 // 7,4 V
uint8_t voltage_load;
uint8_t voltage_no_load;
uint8_t intensity;
uint8_t pwm;
uint8_t counter;
uint8_t yellow;
//uint16_t mega_counter;
#ifdef LOGGING
uint16_t log_count = 0;
void log_init(void) {
log_count = eeprom_read_byte((uint8_t *) 126);
if (log_count > 0) {
uint8_t data = eeprom_read_byte((uint8_t *) log_count);
eeprom_write_byte((uint8_t *)log_count, data);
}
}
void log_byte(uint8_t data) {
if (log_count < 125) {
log_count++;
wdt_reset();
eeprom_busy_wait();
eeprom_write_byte((uint8_t *)log_count, data);
wdt_reset();
eeprom_busy_wait();
eeprom_write_byte((uint8_t *)126, log_count);
}
}
#endif
//initialize watchdog
void WDT_Init(void) {
//disable interrupts
cli();
//reset watchdog
wdt_reset();
//set up WDT interrupt
WDTCR = (1<<WDCE)|(1<<WDE);
//Start watchdog timer with 250ms prescaller
WDTCR |= (1<<WDIE)|(1<<WDE)|(1<<WDP2);
//Enable global interrupts
sei();
}
ISR(WDT_vect) {
WDTCR |= (1<<WDIE);
}
void timer_init(void) {
power_timer0_enable();
// disable global interrupts
cli();
// Set to CTC Mode
TCCR0A = (1 << WGM01);
// set prescaler to 64
TCCR0B = (1 << CS01)|(1 << CS00);
// init timer
TCNT0 = 0;
// set top 64/1000 * 100 = 1,9ms
OCR0A = 30;
//Set interrupt on compare match
TIMSK |= (1 << OCIE0A);
// enable interrupts
sei();
}
ISR (TIM0_COMPA_vect) {
}
void sleep(void) {
cli();
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
sleep_disable();
}
void yellow_LED(void) {
PORTB |= (1<<LED1);
PORTB &= ~(1<<LED2);
}
void red_LED(void) {
PORTB |= (1<<LED2);
PORTB &= ~(1<<LED1);
}
void invert_yellow_LED(void) {
PORTB ^= (1<<LED1);
PORTB &= ~(1<<LED2);
}
void invert_red_LED(void) {
PORTB ^= (1<<LED2);
PORTB &= ~(1<<LED1);
}
void no_LED(void) {
PORTB &= ~((1<<LED1) | (1<<LED2));
}
uint8_t measure_voltage(void) {
uint8_t volt;
power_adc_enable();
// setup A/D convertor
ADMUX = (1<< REFS2) | (1<< REFS1) | (1<<MUX0) | (1<<MUX1) | (1 << ADLAR); // 2,56 V reference, no cap, PB3
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // enable, 1:8 clock
ADCSRA |= (1<<ADSC);
while (! (ADCSRA & (1<<ADIF))); // wait for conversion complete
ADCSRA |= (1<<ADIF);
volt = ADCH;
ADCSRA &= ~(1<<ADEN); // disable converter to save power
power_adc_disable();
return volt;
}
void measure_intensity(void) {
power_adc_enable();
// setup A/D convertor
ADMUX = (1<< REFS2) | (1<< REFS1) | (1<<MUX1) | (1 << ADLAR); // 2,56 V reference, no cap, PB4
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // enable, 1:8 clock
ADCSRA |= (1<<ADSC);
while (! (ADCSRA & (1<<ADIF))); // wait for conversion complete
ADCSRA |= (1<<ADIF);
intensity = ADCH;
ADCSRA &= ~(1<<ADEN); // disable converter to save power
power_adc_disable();
}
void calculate_pwm(uint8_t volt) {
uint32_t wanted = 0;
if (intensity > INTENSITY_MIN) {
wanted = intensity - INTENSITY_MIN;
}
wanted *= WANTED_STEPS;
wanted /= INTENSITY_STEPS;
wanted += WANTED_MIN;
uint32_t power = volt * volt;
pwm = (uint8_t)(wanted * PWM_MAX / power);
if (pwm >= PWM_CEIL) {
pwm = PWM_CEIL;
}
}
int main(void) {
DDRB = (1<<LED1) | (1<<LED2) | (1<<WIRE);
PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<WIRE));
intensity = 0;
counter = 0;
voltage_no_load = 0;
voltage_load = 0;
pwm = 0;
yellow = 1;
//max_intensity = 255;
//mega_counter = 0;
power_all_disable();
set_sleep_mode(SLEEP_MODE_IDLE);
#ifdef LOGGING
log_init();
#endif
no_LED();
/*uint8_t i = 0;
for (i = 0; i < 100; i++) {
_delay_ms(100);
}
log_byte(0);
log_byte(0);
log_byte(0);*/
voltage_no_load = measure_voltage();
measure_intensity();
calculate_pwm(voltage_no_load);
//WDT_Init();
timer_init();
SREG |= (1<<7); // enable interrupts
while(1) {
counter++;
//mega_counter++;
//if (mega_counter >= 25000) {
// mega_counter = 0;
// log_byte(voltage_no_load);
//}
if (counter <= pwm) {
PORTB |= (1<<WIRE);
//yellow_LED();
if (counter == pwm) {
voltage_load = measure_voltage();
//log_byte(voltage);
}
} else {
PORTB &= ~(1<<WIRE);
//no_LED();
}
if (counter >= PWM_MAX) {
counter = 0;
voltage_no_load = measure_voltage();
measure_intensity();
calculate_pwm(voltage_load);
if (voltage_no_load <= WARNING_VOLTAGE) {
yellow = 0;
} else {
yellow = 1;
}
if (voltage_no_load < LOW_VOLTAGE) {
break;
}
//log_byte(voltage);
}
//if (log_count >= 120) {
// red_LED();
//} else
if (yellow) {
invert_yellow_LED();
} else {
invert_red_LED();
}
sleep();
}
PORTB &= ~(1<<WIRE);
power_timer0_disable();
WDT_Init();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
while(1) {
invert_red_LED();
sleep();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment