]> jspc29.x-matter.uni-frankfurt.de Git - avr.git/commitdiff
added button control and PID controller to Peltier cooling device firmware
authorMichael Wiebusch <m.wiebusch@gsi.de>
Wed, 7 Jan 2015 17:57:37 +0000 (18:57 +0100)
committerMichael Wiebusch <m.wiebusch@gsi.de>
Wed, 7 Jan 2015 17:57:37 +0000 (18:57 +0100)
atmega32u4/Pro_Micro_v13_schematic.pdf [new file with mode: 0644]
atmega32u4/cooler/cooler.c
atmega32u4/cooler/pinout.txt

diff --git a/atmega32u4/Pro_Micro_v13_schematic.pdf b/atmega32u4/Pro_Micro_v13_schematic.pdf
new file mode 100644 (file)
index 0000000..b9c4ff6
Binary files /dev/null and b/atmega32u4/Pro_Micro_v13_schematic.pdf differ
index 550a196ec02d52b934d541830261c55f261c747d..e70d2dd276321d55ee44961292d47807a027b343 100644 (file)
@@ -2,6 +2,12 @@
 
 #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)
@@ -29,6 +35,8 @@ uint8_t  ids[NUMSENSORS][8];
 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
@@ -74,17 +82,79 @@ void init(void) {
 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) {
@@ -200,12 +270,52 @@ void printAxes(void) {
   }
   
   
+
+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);    
@@ -232,7 +342,7 @@ __attribute__((naked)) int main(void) {
       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) {
@@ -240,12 +350,26 @@ __attribute__((naked)) int main(void) {
         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);
       }
     }  
   }   
index d6f05c71ee3f3fb74512573ed46eb9ae63dd0f4c..513258686d009c67712fc58cf8d2458e7b3eef3c 100644 (file)
@@ -1,11 +1,21 @@
-7    1-wire
-8    Reset
-9    CS
-10   D/C
-16   SDI
-15   SCK
+The board is compatible to the SparkFun Pro Micro board
 
-A0   TDI
-A1   TDO
-A2   TMS
-A3   TCK
+#arduino  #atmega     #function
+                     
+7         PE6         1-wire
+8         PB4         Reset
+9         PB5         CS
+10        PB6         D/C
+16        PB2(MOSI)   SDI
+15        PB1(SCK)    SCK
+                     
+A0        PF7         TDI
+A1        PF6         TDO
+A2        PF5         TMS
+A3        PF4         TCK
+                     
+2         PD1         Down Key
+3         PD0         Up Key
+                     
+                     
+5         PC6(OC3A)   Peltier Power PWM
\ No newline at end of file