From: Michael Wiebusch Date: Thu, 8 Jan 2015 14:40:12 +0000 (+0100) Subject: added lots of functionality to the cooling controller, first working version X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=845c835a12410b1cf7237f12a2d28ade7ebbd6de;p=avr.git added lots of functionality to the cooling controller, first working version --- diff --git a/atmega32u4/cooler/cooler.c b/atmega32u4/cooler/cooler.c index e70d2dd..df6d170 100644 --- a/atmega32u4/cooler/cooler.c +++ b/atmega32u4/cooler/cooler.c @@ -13,10 +13,13 @@ #define GREEN_ON() PORTD &= ~(1< 5 bit, green -> 6 bit, blue -> 5 bit #define TOP_BACKGROUND() lcd_set_background(0x03,0x04,0x05) #define BOTTOM_BACKGROUND() lcd_set_background(0x00,0x00,0x00) #define FIRST_VALUE_FOREGROUND() lcd_set_foreground(0x1f,0x3f,0x0e);lcd_set_background(0x03,0x04,0x05) #define SECOND_VALUE_FOREGROUND() lcd_set_foreground(0x0e,0x2e,0x1f);lcd_set_background(0x03,0x04,0x05) +#define THIRD_VALUE_FOREGROUND() lcd_set_foreground(31, 63/2 ,31/2);lcd_set_background(0x03,0x04,0x05) #define FIRST_VALUE_BACKGROUND() lcd_set_background(0x1f,0x3f,0x0e) #define SECOND_VALUE_BACKGROUND() lcd_set_background(0x0e,0x2e,0x1f) #define AXES_COLOR() lcd_set_foreground(0x1f,0x3f,0x1f); @@ -34,6 +37,7 @@ volatile uint8_t second, lastsecond; uint8_t ids[NUMSENSORS][8]; uint16_t temps[NUMSENSORS] = {-255}; int16_t set_value = 12*16; +uint8_t output_power_percent = 0; volatile uint8_t keys_pressed = 0b00000000; @@ -103,6 +107,14 @@ void set_PWM_output(uint16_t value){ // 0-1023 } + +void uart_puts(const char *s ) +{ + while (*s) + usb_serial_putchar(*s++); + +}/* uart_puts */ + void print_bin(uint8_t byte) { usb_serial_putchar('0'); @@ -115,6 +127,51 @@ void print_bin(uint8_t byte) { } } } + + + +char stringbuffer[16]; + +// convert an unsigned integer to string +void my_uitoa(uint32_t zahl, char* string, uint8_t no_digits, char leading_char) { + int8_t i; // schleifenzähler + + string[no_digits] = '\0'; // String Terminator + for (i = (no_digits - 1); i >= 0; i--) { + if (zahl == 0 && i < (no_digits - 1)) { + string[i] = leading_char; + } else { + string[i] = (zahl % 10) + '0'; + } // Modulo rechnen, dann den ASCII-Code von '0' addieren + zahl /= 10; + } + +} + +void uart_print_signed_number(int16_t zahl, uint8_t no_digits) { + my_uitoa(abs(zahl),stringbuffer,no_digits,' '); + if (zahl < 0) { + usb_serial_putchar('-'); + } else { + usb_serial_putchar('+'); + } + uart_puts(stringbuffer); +} + +void uart_print_number(int16_t zahl, uint8_t no_digits) { + my_uitoa(zahl,stringbuffer,no_digits,' '); + uart_puts(stringbuffer); +} + +void uart_print_sign(int16_t zahl){ + if (zahl < 0) { + usb_serial_putchar('-'); + } else { + usb_serial_putchar('+'); + } +} + + void keys_init(void){ #define KEYPORT PORTD @@ -275,15 +332,16 @@ void new_set_value(int16_t value){ value = MAX(value,SET_VAL_LOWER); value = MIN(value,SET_VAL_UPPER); set_value = value; + showTemp(1,set_value); } // all constants in x/10 #define PID_CONST_PROP 800 -#define PID_CONST_INT 20 +#define PID_CONST_INT 15 #define PID_CONST_DIFF 0 #define PID_ACTOR_OUTPUT_LIMIT 1023 -#define PID_INTEGRAL_LIMIT 10000 -#define PID_FINE_INTERVAL 2*16 +#define PID_INTEGRAL_LIMIT 600 +#define PID_FINE_INTERVAL 2*16 // within 2 degrees uint16_t pid_calculation(int16_t error) { static int16_t intg_error = 0; @@ -305,11 +363,57 @@ uint16_t pid_calculation(int16_t error) { // output is limited actor = MIN(PID_ACTOR_OUTPUT_LIMIT,actor); last_error = error; + +// //for debug +// uart_puts("integral: "); +// uart_print_signed_number(intg_error,6); +// uart_puts("\n\r"); return actor; } +void showPower(void){ +#define POWER_XPOS 62 +#define POWER_YPOS 48 + + THIRD_VALUE_FOREGROUND(); + if(output_power_percent <10){ + lcd_set_area_xy(POWER_XPOS,POWER_XPOS+29*2,POWER_YPOS,POWER_YPOS+32); + lcd_moveto_xy(POWER_YPOS,POWER_XPOS+29*2); + } else if(output_power_percent <100){ + lcd_set_area_xy(POWER_XPOS,POWER_XPOS+29,POWER_YPOS,POWER_YPOS+32); + lcd_moveto_xy(POWER_YPOS,POWER_XPOS+29); + } else { + lcd_moveto_xy(POWER_YPOS,POWER_XPOS); + } + lcd_put_int(output_power_percent); +} + + +void uartReport(void){ + uart_puts("Setpoint: "); + uart_print_sign(set_value); + uart_print_number(abs(set_value)/16,2); + usb_serial_putchar('.'); + usb_serial_putchar('0'+lut[abs(set_value)%16]); // print post comma + uart_puts(" deg C\n\r"); + + uart_puts("Temperature: "); + uart_print_sign(temps[0]); + uart_print_number(abs(temps[0])/16,2); + usb_serial_putchar('.'); + usb_serial_putchar('0'+lut[abs(temps[0])%16]); // print post comma + uart_puts(" deg C\n\r"); + + uart_puts("PWM Output: "); + uart_print_number(output_power_percent,3); + uart_puts("%\n\r"); + + uart_puts("--------\n\r"); + +} __attribute__((naked)) int main(void) { + init(); usb_init(); lcd_init(); @@ -325,9 +429,18 @@ __attribute__((naked)) int main(void) { lcd_set_foreground(0x1f,0x3f,0x1f); lcd_set_font(FONT_PROP_16,DOUBLE_HEIGHT|SPACING); - lcd_putstr_xy_P(PSTR("Cooling Control"),26,30); + lcd_putstr_xy_P(PSTR("Cooling Control"),10,30); printAxes(); - + + + THIRD_VALUE_FOREGROUND(); + lcd_set_font(FONT_PROP_16,NORMAL); + lcd_putstr_xy_P(PSTR("power"),48,20); + lcd_set_font(FONT_PROP_16,DOUBLE_SIZE|SPACING); + lcd_putstr_xy_P(PSTR("%"),54,150); + + + pushvalue(1,set_value); @@ -343,7 +456,6 @@ __attribute__((naked)) int main(void) { uint16_t t = hex2int(buffer[4])*160 + hex2int(buffer[5])*16 + (((hex2int(buffer[7])*16+8)/10)&0xF); if (buffer[3] == '-') t = t*-1; new_set_value(t); - pushvalue(1,t); } if(n==10) { usb_serial_write(buffer,recvpointer); @@ -353,13 +465,11 @@ __attribute__((naked)) int main(void) { if(key_was_pressed(1< 30*16){ // turn off peltier if temperature is off limits (>30 deg C) + set_PWM_output(0); + output_power_percent = 0; + } else { + uint16_t pid_output = pid_calculation( temps[0] - set_value ); + set_PWM_output(pid_output); // let PID compute output + output_power_percent = MIN(100,pid_output/10); // output power in percent (ignore the last 23 from 1023) + } + showPower(); + uartReport(); } } }