#define GREEN_ON() PORTD &= ~(1<<PD5)
#define GREEN_OFF() PORTD |= (1<<PD5)
+
+// 16 bit color code: red -> 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);
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;
}
+
+void uart_puts(const char *s )
+{
+ while (*s)
+ usb_serial_putchar(*s++);
+
+}/* uart_puts */
+
void print_bin(uint8_t byte) {
usb_serial_putchar('0');
}
}
}
+
+
+
+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
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;
// 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();
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);
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);
if(key_was_pressed(1<<KEY_UP)) {
new_set_value(set_value + 16);
- usb_serial_putchar('U');
- showTemp(1,set_value);
+// usb_serial_putchar('U');
}
if(key_was_pressed(1<<KEY_DOWN)) {
new_set_value(set_value - 16);
- usb_serial_putchar('D');
- showTemp(1,set_value);
+// usb_serial_putchar('D');
}
if(second != lastsecond) {
start_meas();
pushvalue(0,temps[0]);
lastsecond = second;
- set_PWM_output(pid_calculation( temps[0] - set_value ));
-// print_bin(keys_pressed);
+
+ if(temps[0] > 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();
}
}
}