#include "main.h"
+#define SET_VAL_UPPER 30*16 //upper limit to set value
+#define SET_VAL_LOWER -10*16 //lower limit to set value
+
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+
#define YELLOW_ON() PORTB &= ~0x1
#define YELLOW_OFF() PORTB |= 0x1
#define GREEN_ON() PORTD &= ~(1<<PD5)
uint16_t temps[NUMSENSORS] = {-255};
int16_t set_value = 12*16;
+volatile uint8_t keys_pressed = 0b00000000;
+
#define MINX 19
#define MAXX 318
#define MINY 100
void timer_init(void) {
TCCR0A = (1<<WGM01); //CTC
TCCR0B = (4<<CS00); // /256
- OCR0A = 167;
+ OCR0A = 156;
TIMSK0 = (1<<OCIE0A);
}
+
+void PWM_init(void) {
+ DDRC |= 1<<PC6; // peltier PWM pin as output
+// PORTC |= 1<<PC6;
+ TCCR3A |= 1<<COM3A1 | 0<<COM3A0; // clear output on compare match
+ TCCR3A |= 1<<WGM31 | 1<<WGM30; // fast PWM, 10 bit ...
+ TCCR3B |= 0<<WGM33 | 0<<WGM32; // ...
+ TCCR3B |= 1<<CS32 | 0<<CS31 | 0<<CS30; // clock source from /256 prescaler
+ // (this should yield a PWM frequency of 30 Hz)
+ OCR3A = 0; // start with output = off
+}
+
+void set_PWM_output(uint16_t value){ // 0-1023
+ OCR3A = value;
+}
+
+
+void print_bin(uint8_t byte) {
+
+ usb_serial_putchar('0');
+ usb_serial_putchar('b');
+ for (uint8_t i=0; i<8; i++){
+ if(byte & (1<<i)){
+ usb_serial_putchar('1');
+ } else {
+ usb_serial_putchar('0');
+ }
+ }
+}
+
+void keys_init(void){
+#define KEYPORT PORTD
+#define KEYDDR DDRD
+#define KEYPIN PIND
+#define KEY_UP PD0
+#define KEY_DOWN PD1
+#define ACTIVE_KEYS_MASK (1<<KEY_UP|1<<KEY_DOWN)
+
+ KEYDDR &= ~ACTIVE_KEYS_MASK; // as input
+ KEYPORT |= ACTIVE_KEYS_MASK; // use pullup
+}
+
+
+
+void scan_keys(void){
+ static uint8_t key_state_m0, key_state_m1;
+ uint8_t key_state = ~(KEYPIN) & ACTIVE_KEYS_MASK;
+ // -------has state changed?---- --- is key pressed now? ---
+ keys_pressed |= (key_state_m0 ^ key_state_m1) & key_state;
+
+ key_state_m1 = key_state_m0;
+ key_state_m0 = key_state;
+}
+
+uint8_t key_was_pressed(uint8_t key_mask){
+ // was one of the keys defined by key mask pressed?
+ uint8_t result = keys_pressed & key_mask;
+ keys_pressed &= ~(key_mask);
+ return result;
+}
+
ISR(TIMER0_COMPA_vect ) {
static uint8_t cnt = 0;
cnt++;
- if(cnt == 167) {
+ if(cnt == 200) {
cnt = 0;
second++;
}
+ scan_keys();
}
uint8_t hex2int(char c) {
}
+
+void new_set_value(int16_t value){
+ value = MAX(value,SET_VAL_LOWER);
+ value = MIN(value,SET_VAL_UPPER);
+ set_value = value;
+}
+
+// all constants in x/10
+#define PID_CONST_PROP 800
+#define PID_CONST_INT 20
+#define PID_CONST_DIFF 0
+#define PID_ACTOR_OUTPUT_LIMIT 1023
+#define PID_INTEGRAL_LIMIT 10000
+#define PID_FINE_INTERVAL 2*16
+
+uint16_t pid_calculation(int16_t error) {
+ static int16_t intg_error = 0;
+ static int16_t last_error = 0;
+ int16_t diff_error = error-last_error;
+
+ if( abs(error)<PID_FINE_INTERVAL ) { // use integral only inside a fine interval
+ intg_error += error;
+ intg_error = MAX(-PID_INTEGRAL_LIMIT,intg_error);
+ intg_error = MIN(PID_INTEGRAL_LIMIT,intg_error);
+ }
+
+ int32_t actor =
+ ((intg_error * PID_CONST_INT )/10)
+ + ((diff_error * PID_CONST_DIFF)/10)
+ + ((error * PID_CONST_PROP)/10);
+ // allow only positive values;
+ actor = MAX(0,actor);
+ // output is limited
+ actor = MIN(PID_ACTOR_OUTPUT_LIMIT,actor);
+ last_error = error;
+ return actor;
+}
+
__attribute__((naked)) int main(void) {
init();
usb_init();
lcd_init();
timer_init();
+ keys_init();
+ PWM_init();
lcd_command_1(LCD_MIRROR, LCD_BGR | LCD_FLIP_XY);
lcd_command(LCD_ON);
if(n == 10 && recvpointer >= 8 && buffer[0] == 'S' && buffer[1] == 'E' && buffer[2] == 'T') { //SETsvv.v
uint16_t t = hex2int(buffer[4])*160 + hex2int(buffer[5])*16 + (((hex2int(buffer[7])*16+8)/10)&0xF);
if (buffer[3] == '-') t = t*-1;
- set_value = t;
+ new_set_value(t);
pushvalue(1,t);
}
if(n==10) {
recvpointer = 0;
}
}
+
+ if(key_was_pressed(1<<KEY_UP)) {
+ new_set_value(set_value + 16);
+ usb_serial_putchar('U');
+ showTemp(1,set_value);
+ }
+ if(key_was_pressed(1<<KEY_DOWN)) {
+ new_set_value(set_value - 16);
+ usb_serial_putchar('D');
+ showTemp(1,set_value);
+ }
+
if(second != lastsecond) {
usb_serial_putchar(0x10);
read_meas();
start_meas();
pushvalue(0,temps[0]);
lastsecond = second;
+ set_PWM_output(pid_calculation( temps[0] - set_value ));
+// print_bin(keys_pressed);
}
}
}