]> jspc29.x-matter.uni-frankfurt.de Git - avr.git/commitdiff
added lots of functionality to the cooling controller, first working version
authorMichael Wiebusch <m.wiebusch@gsi.de>
Thu, 8 Jan 2015 14:40:12 +0000 (15:40 +0100)
committerMichael Wiebusch <m.wiebusch@gsi.de>
Thu, 8 Jan 2015 14:40:12 +0000 (15:40 +0100)
atmega32u4/cooler/cooler.c

index e70d2dd276321d55ee44961292d47807a027b343..df6d17019c02c6503149d6a7e30c58416d105de9 100644 (file)
 #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);
@@ -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<<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) {
@@ -368,8 +478,17 @@ __attribute__((naked)) int main(void) {
       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();
       }
     }  
   }