From 7b394b340f9365f9c8eae9f5732b9de6c9a992b6 Mon Sep 17 00:00:00 2001
From: Pontus Giselsson <pontus.giselsson@control.lth.se>
Date: Thu, 12 Feb 2009 13:23:38 +0000
Subject: [PATCH] Added mutex for shared variables

---
 .../avr/current_control_final.c               |  72 +++++----
 linear_pendulum_2009/avr/pccom.c              |  34 +++-
 linear_pendulum_2009/avr/vel_control.c        | 152 ++++++++++--------
 linear_pendulum_2009/avr/vel_control.h        |   2 +
 4 files changed, 153 insertions(+), 107 deletions(-)

diff --git a/linear_pendulum_2009/avr/current_control_final.c b/linear_pendulum_2009/avr/current_control_final.c
index dd4b96c..2c0f1bd 100644
--- a/linear_pendulum_2009/avr/current_control_final.c
+++ b/linear_pendulum_2009/avr/current_control_final.c
@@ -7,19 +7,22 @@
 
 // control variables
 volatile int16_t ref=0;   // reference value (from velocity controller)
-volatile unsigned char lbyte,hbyte;  
 volatile int16_t y;       // measurement, 9 frac bits
-volatile uint8_t low, high;
+volatile uint8_t low, high;  // when reading AD-conversion
 volatile int16_t e = 0;   // control error, 9 frac bits
 volatile int16_t v = 0;   // temporary ctrl signal, 9 frac bits
 volatile int16_t I = 0;   // integral part of ctrl, 13 frac bits
-volatile int16_t u = 0;   // ctrl signal = pwm high time
-volatile int16_t K = 74; // 7 frac bits
-volatile int16_t Ke = 26; //7 frac bits, K*h/Ti
+volatile int16_t u = 0;   // ctrl signal = pwm high time (8 bits)
+volatile int16_t K = 74;  // 7 frac bits
+volatile int16_t Ke = 26;  // 7 frac bits, K*h/Ti
 volatile int16_t Ksat = 44; // 7 frac bits, h/Tr
 
+// twi variable
+volatile int16_t status;
+
 
 // logging variables
+/*
 #define log_len 100
 volatile int16_t ctrl_log[log_len];
 volatile int16_t error_log[log_len];
@@ -28,12 +31,23 @@ volatile int16_t skipSamples = 1000;
 volatile int16_t countSamples = 0;
 volatile int16_t jj=0;
 volatile int8_t stop = 0;
+*/
+
 
-// twi variables
-volatile int16_t status;
 
 
+/* Routine used to transmit bytes on the serial port */
+/*
+static void putchar(unsigned char ch)
+{
+	while ((inp(UCSRA) & 0x20) == 0) {};
+	outp(ch, UDR);
+	while ((inp(UCSRA) & 0x20) == 0) {};
+}
+*/
+
 /* Send logged data over Serial connection */
+ /*
 static inline void sendData() {
   int16_t ii = 0;
   while (ii < log_len) {
@@ -54,16 +68,16 @@ static inline void sendData() {
     ii++;
   }
 }
+ */
 
 
 
-
-/* Timer 2 compare match interupt */
+/* Timer 2 compare match interupt, 28.8 kHz, syncronized with pwm-period */
 SIGNAL(SIG_OUTPUT_COMPARE2) {
   // Start AD conversion
   ADCSRA |= BV(ADSC);
   
-  // Read input
+  // Read previous AD-conversion result
   low = inp(ADCL);
   high = inp(ADCH);
   y =  ((high<<8) | low) - 512; //y 9 frac bits
@@ -71,15 +85,16 @@ SIGNAL(SIG_OUTPUT_COMPARE2) {
   //control error, (+) since negative measurements
   e = ref+y; //e 9 frac bits
   
+  // temporary ctrl-signal
   v = (int16_t)(((K*e+64)>>7)+(I>>4));
 
-  //saturation and update integral part of ctrl
+  //saturation and update integral part of ctrl with antiwindup
   if (v > 511) {
-    I = I + (((Ke*e) + (Ksat)*(511-v))>>3);
+    I = I + ((((Ke*e) + (Ksat)*(511-v))+(1<<2))>>3);
   } else if (v < -512) {
-    I = I + (((Ke*e) + (Ksat)*(-512-v))>>3);
+    I = I + ((((Ke*e) + (Ksat)*(-512-v))+(1<<2))>>3);
   } else {
-    I = I + ((Ke*e)>>3);
+    I = I + ((Ke*e+(1<<2))>>3);
   }
   
   // ctrl signal, 7 bits + direction
@@ -94,19 +109,20 @@ SIGNAL(SIG_OUTPUT_COMPARE2) {
 
   // set pwm switching time
   if (u < 0) {
-    PORTC |= 0x80;
-    OCR1BL = (unsigned char) (128-(-u));
+    PORTC |= 0x80;  // set direction of motion
+    OCR1BL = (unsigned char) (128-(-u)); // set length of pwm-high
   } else {
-    PORTC = (PORTC & 0x7F);
-    OCR1BL = (unsigned char) (127-u);
+    PORTC = (PORTC & 0x7F); // set direction of motion
+    OCR1BL = (unsigned char) (127-u); // set length of pwm-high
   }
 
   // TWI-communication, recieve reference from velocity controller
   if ((BV(TWINT)&inp(TWCR))) {
     status = (inp(TWSR)&0xf8);
+    // status 0x80 means data recieved
     if (status == 0x80) {
-      ref = (int16_t)((int8_t)(inp(TWDR))); // read reference
-      ref = ref << 2;  // shifted 2 steps for 10 bits for reference
+      ref = (int16_t)((int8_t)(inp(TWDR))); // read 8 bit reference
+      ref = ref << 2;  // shift up 2 steps for 10 bits for reference in loop
     } 
     else {
     }
@@ -137,13 +153,13 @@ SIGNAL(SIG_OUTPUT_COMPARE2) {
 
 int main()
 {
-  // clear interrupts
+  // clear interrupts (might not be needed)
   cli();
   
   //Port directions
-  outp(0x08,PORTC); // pull up on overtemp signals
-  outp(0xa0,DDRC);  // output on dir and brake
-  outp(0x10,DDRD);  // output on pwm
+  outp(0x08,PORTC); // pull up on overtemperature signals
+  outp(0xa0,DDRC);  // output on direction and brake
+  outp(0x10,DDRD);  // output on pwm-signal
   
   /* Timer section */
   
@@ -151,7 +167,7 @@ int main()
   outp(BV(COM1A1)|BV(COM1B1)|BV(COM1A0)|BV(COM1B0)|BV(WGM11)|BV(WGM10),TCCR1A);
   outp(BV(CS10)|BV(WGM13)|BV(WGM12),TCCR1B);
   
-  // Reset Timer1 and set TOP-value to 128 (means 7-bit pwm-signal-> h_pwm=8.61 micros)
+  // Reset Timer1 and set TOP-value to 128 (means 7-bit pwm-signal-> 115.2 kHz)
   outp(0x00,OCR1AH);
   outp(0x7f,OCR1AL);
   outp(0x00,TCNT1H);
@@ -160,7 +176,7 @@ int main()
   outp(0x7f,OCR1BL); // to not start motor-rotation before control
 
   
-  /* Timer 2, 4 times pwm-period, for control sampling, prescaler 8 */
+  /* Timer 2, 4 times pwm-period, for control sampling, prescaler 8, 28.8 kHz */
   outp(BV(WGM21)|BV(CS21),TCCR2);
   outp(0x3f,OCR2);
   /* Reset timer 2 */
@@ -171,12 +187,12 @@ int main()
 
   //Serial communication
   outp(0x00, UCSRA);	// USART:
-  outp(0x18, UCSRB);	// USART: RxIntEnable|RxEnable|TxEnable
+  outp(0x18, UCSRB);	// USART: RxEnable|TxEnable
   outp(0x86, UCSRC);	// USART: 8bit, no parity
   outp(0x00, UBRRH);	// USART: 115200 @ 14.7456MHz
   outp(7,UBRRL);	// USART: 115200 @ 14.7456MHz
   
-  /* AREF (AREF is 5V) pin external capacitor, MUX0 for current */
+  /* AREF (AREF is 5V) pin external capacitor, MUX0 for current measurement */
   outp(BV(REFS0)|BV(MUX0),ADMUX); 	
   
   // Enable ADC, start first conversion, prescaler 32, not free running mode
diff --git a/linear_pendulum_2009/avr/pccom.c b/linear_pendulum_2009/avr/pccom.c
index 4991404..7187302 100644
--- a/linear_pendulum_2009/avr/pccom.c
+++ b/linear_pendulum_2009/avr/pccom.c
@@ -25,7 +25,8 @@
 
 #define POLL_AXIS1_POSITION      0x0001
 #define POLL_AXIS1_VELOCITY      0x0002
-//#define POLL_PEND_ANGLE          0x0004
+#define POLL_PEND_ANGLE          0x0004
+#define POLL_CURRENT_REFERENCE   0x0008
 //#define POLL_AXIS1_RESET         0x0008
 #define POLL_CONFIG              0x8000
 
@@ -60,7 +61,8 @@ void pccom_receiveByte(char ch)
     switch (serialio_channel) {
     case 0:  { addPoll(POLL_AXIS1_POSITION); } break;
     case 1:  { addPoll(POLL_AXIS1_VELOCITY); } break;
-      //case 2:  { addPoll(POLL_PEND_ANGLE); } break;
+    case 2:  { addPoll(POLL_PEND_ANGLE); } break;
+    case 3:  { addPoll(POLL_CURRENT_REFERENCE); } break;
     case 31: { addPoll(POLL_CONFIG); } break;
     }
   } break;
@@ -89,13 +91,21 @@ static uint8_t sendConfigPacket(uint8_t position)
     case 1: CONF_ANALOG_IN(0, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
     case 2: CONF_ANALOG_IN(0, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
 
-      case 3: CONF_ANALOG_IN(1, CONF_RESOLUTION(18)); break;     // Velocity estimate
-      case 4: CONF_ANALOG_IN(1, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
-      case 5: CONF_ANALOG_IN(1, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+    case 3: CONF_ANALOG_IN(1, CONF_RESOLUTION(18)); break;     // Velocity estimate
+    case 4: CONF_ANALOG_IN(1, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+    case 5: CONF_ANALOG_IN(1, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+
+    case 6: CONF_ANALOG_IN(2, CONF_RESOLUTION(10)); break;     // Pend angle measurement
+    case 7: CONF_ANALOG_IN(2, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+    case 8: CONF_ANALOG_IN(2, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+
+    case 9: CONF_ANALOG_IN(3, CONF_RESOLUTION(8)); break;     // Pend angle measurement
+    case 10: CONF_ANALOG_IN(3, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+    case 11: CONF_ANALOG_IN(3, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
  
-     case 6: CONF_ANALOG_OUT(0, CONF_RESOLUTION(13)); break;    // Reference to vel-ctrl
-     case 7: CONF_ANALOG_OUT(0, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
-     case 8: CONF_ANALOG_OUT(0, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+    case 12: CONF_ANALOG_OUT(0, CONF_RESOLUTION(13)); break;    // Reference to vel-ctrl
+    case 13: CONF_ANALOG_OUT(0, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+    case 14: CONF_ANALOG_OUT(0, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
       
     default: CONF_END(); return 0;
   }
@@ -118,6 +128,14 @@ static uint8_t sendNextPacket() // returns 1 if a packet was available
     toPoll &= ~POLL_AXIS1_VELOCITY;
     serialio_putchannel(1, getVelocity()+(1L<<17)); 
   }
+  else if (toPoll & POLL_PEND_ANGLE) { 
+    toPoll &= ~POLL_PEND_ANGLE;
+    serialio_putchannel(2, getAngle()+(1L<<9)); 
+  }
+  else if (toPoll & POLL_CURRENT_REFERENCE) { 
+    toPoll &= ~POLL_CURRENT_REFERENCE;
+    serialio_putchannel(3, getCurrentRef()+(1L<<7)); 
+  }
   else if (toPoll & POLL_CONFIG) {
     if (configPosition < 0) configPosition = 0; // Start sending config?   
     if (!sendConfigPacket(configPosition)) {    // Last packet?
diff --git a/linear_pendulum_2009/avr/vel_control.c b/linear_pendulum_2009/avr/vel_control.c
index 3b10f60..204a3a8 100644
--- a/linear_pendulum_2009/avr/vel_control.c
+++ b/linear_pendulum_2009/avr/vel_control.c
@@ -11,14 +11,12 @@
 
 // reference variables
 volatile int32_t ref = 0;  // 11 frac bits
-volatile int16_t refFlag = 0;
-volatile int16_t deltaRef = 1;
-volatile int16_t refCount = 0;
-volatile int32_t refTest = 0;
+volatile int32_t refCtrl = 0;
 
 
 // velocity control variables
 volatile int32_t u = 0;  // 11 frac bits
+volatile int32_t uSend = 0;
 volatile int32_t v = 0;  // 11 frac bits
 volatile int8_t brake = 0;
 volatile int32_t I = 0; // 11 frac bits
@@ -35,6 +33,7 @@ volatile int32_t Ksat = 3; // 6 frac bits
 
 volatile int16_t pos = 0;
 volatile int16_t posTemp = 0;
+volatile int16_t posCtrl = 0;
 volatile int16_t oldPos = 0;
 volatile int8_t newX;
 volatile int8_t newY;
@@ -44,24 +43,43 @@ volatile int8_t sum = 0;
 
 // velocity estimation parameters
 volatile int32_t velEst = 0; // 5 frac bits
-volatile int32_t velEstTemp = 0; 
+//volatile int32_t velEstTemp = 0; 
+volatile int32_t velEstSend = 0;
 int16_t a = 116; //7 frac bits
 int16_t b = 152; // 5 frac bits
 
+// adc measurement variables
+volatile int16_t low;
+volatile int16_t high;
 
 // return position (in tics) 
 int32_t getPosition() {
+  cli();
   posTemp = pos;
+  sei();
   return ((int32_t) posTemp);
 }
 
 
 // return velocity (in mm/s) 
 int32_t getVelocity() {
-  return velEst;
+  return velEstSend;
+}
+
+// return last angle measurement
+int16_t getAngle() {
+  low = inp(ADCL);
+  high = inp(ADCH);
+  return ((int16_t) ((high<<8) | low) - 512);
+}
+
+// return current reference
+int32_t getCurrentRef() {
+  return uSend;
 }
 
 
+
 /* Routine used to set the red LED */
 void setLED(uint8_t on)
 {
@@ -82,16 +100,16 @@ void initPos()
   oldY = ENCODERY;
 }
 
-/* Routine used to track the cart position */
-void setPos()
+/* Routine used to reset the cart position */
+void resetPos()
 {
-
+  
 }
 
 /* Timer 2, Encoder counter, 73 kHz */
 SIGNAL(SIG_OUTPUT_COMPARE2) {
 
-   
+  
 
   // Update position from encoder
   newX = ENCODERX;
@@ -118,7 +136,7 @@ SIGNAL(SIG_OUTPUT_COMPARE2) {
       oldY = newY;
   }
 
-
+  
 
 }
 
@@ -126,12 +144,10 @@ SIGNAL(SIG_OUTPUT_COMPARE2) {
 /* Timer 1, serial communication */
 SIGNAL(SIG_OUTPUT_COMPARE0) {
 
-  TIMSK &= ~(BV(OCIE1A)|BV(OCIE0));
-
-  sei(); // enable interrupts from timer 0 and timer 2
-  
-  //PORTC |= 0x10;  // to clock calulation time
+  TIMSK &= ~(BV(OCIE0)|BV(OCIE1A));
 
+  sei(); // enable interrupts from timer 0 and timer 2  
+    PORTC |= 0x10;  // to clock calulation time
   uint8_t status = UCSRA;
   if (status & (1<<RXC)) {
     char ch = UDR;
@@ -147,31 +163,42 @@ SIGNAL(SIG_OUTPUT_COMPARE0) {
     int16_t toSend = pccom_getNextByteToSend();
     if (toSend >= 0) UDR = (char)toSend;
   }
-  //PORTC &= ~0x10; 
   
-  TIMSK |= (BV(OCIE1A)|BV(OCIE0)); 
- 
+  PORTC &= ~0x10;   
+  TIFR = (1<<OCF0);
+  //TIFR = (1<<OCF1A);
+
+  TIMSK |= (BV(OCIE0)|BV(OCIE1A)); 
+
 }
 
 
 
 /* Timer 0, control loop , 1 kHz */
 SIGNAL(SIG_OUTPUT_COMPARE1A) {
-
-  TIMSK &= ~(BV(OCIE0)|BV(OCIE1A));
   
-  sei(); // to enable interupts from timer2
+  TIMSK &= ~(BV(OCIE1A));
 
-   
+  posCtrl = pos; // to aviod overwrite while reading
+
+  sei(); // to enable interupts from timer2
 
+ 
   // linear velocity estimator
-  // velocity estimate in mm/s 
-  velEst = (((a*velEst+64)>>7)+b*(pos-oldPos));  // 5 fracbits on velEst
-  oldPos = pos;
+  // velocity estimate in mm/s
+  velEst = (((a*velEst+64)>>7)+b*(posCtrl-oldPos));  // 5 fracbits on velEst
+  oldPos = posCtrl;
+
+  // emergency stop
+  ref = ref*(1-brake);
+  
+  cli();
+  velEstSend = velEst;
+  refCtrl = ref;
+  sei();
 
   // control error
-  //e = ref-((int16_t)((velEst+16)>>5));  // mm/s
-  e = ref-((velEst+16)>>5);  // mm/s
+  e = refCtrl-((velEst+16)>>5);  // mm/s
   
   v = (((K*e+(1<<5))>>6)+((I+(1<<3))>>4));
 
@@ -181,13 +208,13 @@ SIGNAL(SIG_OUTPUT_COMPARE1A) {
   } else if (v < -2048) {
     I = I + ((((Ke*e) + (Ksat)*(-2048-v))+(1<<1))>>2);
   } else {
-    I = I + ((Ke*e+(1<<3))>>2);
+    I = I + ((Ke*e+(1<<1))>>2);
   }
   
   u = (v+8)>>4; //8 frac bits to current loop
 
   // friction compensation
-  if (ref > 0) {
+  if (refCtrl > 0) {
     u = u+10;
   } else if (ref < 0) {
     u = u-10;
@@ -200,42 +227,23 @@ SIGNAL(SIG_OUTPUT_COMPARE1A) {
     u = -128;
   }
 
-  //u = 2;
+  cli();
+  uSend = u;
+  sei();
 
-  /*
-  // reference calculations
-  refCount++;
   
+  // reset position, velocity estimate and integral part of ctrl if reset button pushed
   
-  if (refFlag == 0) {
-    if  (refCount%1 == 0)
-      ref = ref+deltaRef;
-    if (refCount == 500) {
-      refFlag = 1;
-      deltaRef = -deltaRef;
-      refCount = 0;
-    }
-  } else {
-    if  (refCount%1 == 0)
-      ref = ref+deltaRef;
-    if (refCount == 1000) {
-      refCount = 0;
-      deltaRef = -deltaRef;
-    }
-  }
-  */
-
-  /*
-  if (refCount == 1000) {
-    ref = 0;
+  if (!(PIND & 0x40)) {
+    cli();
+    pos = 0; // reset position
+    sei();
+    oldPos = 0;
+    velEst = 0; // reset velocity estimate
+    I = 0; // reset integral part of controller
+    u = 0; // reset ctrl signal
   }
-  */
-
-  
-  ref = ref*(1-brake);
-
   
-
   // TWI-communication
   // send start command
   outp(BV(TWINT)|BV(TWEN)|BV(TWSTA),TWCR);
@@ -260,9 +268,10 @@ SIGNAL(SIG_OUTPUT_COMPARE1A) {
 
  
 
-  TIMSK |= (BV(OCIE0)|BV(OCIE1A));
-
+  //TIFR = (1<<OCF0); 
+  TIFR = (1<<OCF1A); 
 
+  TIMSK |= (BV(OCIE1A));
 
 }
 
@@ -307,21 +316,22 @@ int main()
   /* Timer 1, 1 kHz */
   outp(BV(WGM12)|BV(CS10),TCCR1B);
   outp(0x39,OCR1AH);
-  outp(0x99,OCR1AL);
+  outp(0x7f,OCR1AL);
   outp(0,TCNT1H);
   outp(0,TCNT1L);
   
 
-  /* Timer 0, 10 kHz, Prescaler 64 */
-  outp(BV(WGM01)|BV(CS01)|BV(CS00),TCCR0);
+  /* Timer 0, 10 kHz, Prescaler 8 */
+  outp(BV(WGM01)|BV(CS01),TCCR0);
   //outp(200,OCR0);
-  outp(23,OCR0); // 10 kHz
+  outp(184-1,OCR0); // 10 kHz
 
   /* Reset timer 0 */
   outp(0,TCNT0);
   //----------------------------------------------------------
 
-  
+  // syncronization (timer1 interrupt 34 micros before timer0 interrupt)
+  TCNT1 = TCNT0*8+500;
   
   
   //Serial communication
@@ -334,10 +344,10 @@ int main()
 
   
   /* AREF (AREF is 5V) pin external capacitor, MUX0 for current */
-  //outp(BV(REFS0)|BV(MUX3),ADMUX);
+  outp(BV(REFS0)|BV(MUX0)|BV(MUX1),ADMUX);
   
-  // Enable ADC, start first conversion, prescaler 32, free running mode
-  //outp(BV(ADEN)|BV(ADSC)|BV(ADPS2)|BV(ADPS0),ADCSRA);
+  // Enable ADC on mux3, start first conversion, prescaler 128, free running mode
+  outp(BV(ADEN)|BV(ADSC)|BV(ADATE)|BV(ADPS2)|BV(ADPS1)|BV(ADPS0),ADCSRA);
 
 
   // Initialize Master TWI
diff --git a/linear_pendulum_2009/avr/vel_control.h b/linear_pendulum_2009/avr/vel_control.h
index 3ffacdd..88d833b 100644
--- a/linear_pendulum_2009/avr/vel_control.h
+++ b/linear_pendulum_2009/avr/vel_control.h
@@ -5,5 +5,7 @@
 void setRef(int32_t newRef);
 int32_t getPosition();
 int32_t getVelocity();
+int16_t getAngle();
+int32_t getCurrentRef();
 
 #endif
-- 
GitLab