• No results found

Appendix D – Program Listing

In document Electronics Hobby Circuits (Page 93-100)

/********************************************* This program was produced by the

CodeWizardAVR V1.0.1.7b Evaluation Automatic Program Generator © Copyright 1998-2001

Pavel Haiduc, HP InfoTech S.R.L. http://infotech.ir.ro

e-mail:[email protected] , [email protected] Project : Thesis - torque motor control Version :

Date : 20/07/2001 Author : Jeffrey Jordan

Company : University of Queensland Comments:

Chip type : AT90S8535 Clock frequency : 4.000000 MHz Memory model : Small Internal SRAM size : 512 External SRAM size : 0 Data Stack size : 128

*********************************************/ #include <90s8535.h>

#include <delay.h> // Floating number to string #include <Ftoa.h>

// String to floating point number #include <Atof.h>

// Standard Input/Output functions #include <stdio.h>

// standard library #include <stdlib.h> // charater type library #include <ctype.h>

#define UART_txReady 0x40

// All variables for the controller, block parameters from simulink model

double Gain_Gain; // Expression: 1.152

double Current_Limiter_US; // Exp: 14

double Current_Limiter_LS; // exp: -14

double Gain1_Gain; // exp 2.84

double Discrete_Time_Integ_IC; // exp 0

double Discrete_Time_Integ_US; // exp 120

double Discrete_Time_Integ_LS; // exp 0

double Voltage_Limiter_US; // exp 120

double Voltage_Limiter_LS; // exp 0

double Varm_to_Duty_ratio_Gain; // exp 1/120

double Gain2_Gain; // exp 310

// Inputs, output double Torque_Input; double Motor_Current; double Duty_Ratio; double Field_Duty_Ratio; // Limited discrete integrator block double Discrete_Time_Integrator; // for discrete integrator gain and update double Gain2;

// pwm for updating the output duty ratio double pwm;

// the desired torque from the user through comms char Tdesired[15];

// a/d value int adval;

double Tinput;

// int to test if first current read, ie zero current for the ref, 0 no, 1 yes int first;

// reference a/d reading for +ve and -ve current reading int ref;

// UART Receiver interrupt service routine #pragma savereg-

interrupt [UART_RXC] void uart_rx_isr(void) {

unsigned char received;

int i;

received = getchar(); delay_ms(10);

if (isdigit(received)) { i = 0;

// providing only digits and 1 decimal point received, 15 is array length while ((received != 's')&(i < 14)) {

Tdesired[i] = received; received = getchar(); ++i; } // convert to a double Tinput = atof(Tdesired); printf("%s \n",Tdesired);

putchar(13); // line feed

// clear Tdesired

for (i=0; i<=14;i++) {

Tdesired[i] = '\0';

} } }

#pragma savereg+

// Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) {

// PWM - do nothing }

// Timer 1 output compare B interrupt service routine interrupt [TIM1_COMPB] void timer1_compb_isr(void) {

// PWM - do nothing }

// Read the ADC conversion result

unsigned int read_adc(unsigned char channel) {

unsigned int channelValue; ADMUX = channel; // Start Conversion ADCSR.6 = 1; // Wait until A2D finished

while (ADCSR.4 == 0); // clear the ADC complete flag ADCSR.4 = 1;

// Read ADC-result - always read ADCL first channelValue = ADCL;

channelValue = channelValue + ((int)(ADCH) << 8);

return channelValue;

} /*

* initialise_param - initialise all the block parameters and other variables */ void initialise_param(void) { Gain_Gain = 1.152; Current_Limiter_US = 14.0; Current_Limiter_LS = -14.0; Gain1_Gain = 2.84; Discrete_Time_Integ_IC = 0.0; Discrete_Time_Integ_US = 120.0;

Discrete_Time_Integ_LS = 0.0; Voltage_Limiter_US = 120.0; Voltage_Limiter_LS = 0.0; Varm_to_Duty_ratio_Gain = 0.008333333333333; Gain2_Gain = 310.0; Torque_Input = 0.0; Motor_Current = 0.0; Duty_Ratio = 0.0; Field_Duty_Ratio = 0.0; Tinput = 0.0; Discrete_Time_Integrator = Discrete_Time_Integ_IC; first = 0; } /*

* read_current - take a reading of the motor current */ void read_current(void) { // a/d voltage - 4.8 // 10 bit - 1023 // amp gain - 56.28 // sensing resistors - 0.005 // no. of resistors - 1 double currentScaler; //currentScaler = (4.8/(1023*56.28))*(1/0.005); currentScaler = 0.016674065;

// read in the reference voltage for the current, pin 5 if (first == 0) {

ref = read_adc(6);

first = 1; }

//read in the current through the a/d converter, pin 6 adval = read_adc(6);

// convert the a/d reading into a current in Amps Motor_Current = ((double)(adval - ref))*currentScaler; }

/*

* read_torque - get the desired torque */

void read_torque(void) {

double torqueScaler;

torqueScaler = 0.009384164223; // = 4.8*2/1023, 1 volt = 2 Nm of torque // read in the desired torque

// two methods

// a/d converter - pin 7

// voltage between 0 and 4.8V unless external reference voltage used adval = read_adc(7); // actual value in volts = (adval/1023) * 4.8V

Torque_Input = ((double)adval)*torqueScaler; // serial comms - need to use uart interrupt //Torque_Input = Tinput;

} /*

* controller_outputs - calculates all of the block outputs for the controller */

void controller_outputs(void) {

// Local Temp variables for controller calculations

double temp1;

double temp2;

double temp3;

// start controller calculations // Gain block Gain

// Saturation block - current limiter if (temp2 >= Current_Limiter_US) {

temp2 = Current_Limiter_US;

} else if (temp2 <= Current_Limiter_LS) {

temp2 = Current_Limiter_LS;

} // Sum block 1

temp2 = temp2 - Motor_Current; // Gain block Gain1

temp3 = temp2 * Gain1_Gain; // Limited discrete integrator block temp1 = Discrete_Time_Integrator; if (temp1 >= Discrete_Time_Integ_US) {

temp1 = Discrete_Time_Integ_US;

} else if (temp1 <= Discrete_Time_Integ_LS) {

temp1 = Discrete_Time_Integ_LS;

} // Sum Block 2 temp3 = temp3 + temp1; // Saturate Block Voltage Limiter if (temp3 >= Voltage_Limiter_US) {

temp3 = Voltage_Limiter_US;

} else if (temp3 <= Voltage_Limiter_LS) {

temp3 = Voltage_Limiter_LS;

}

// Gain Block Varm to Duty ratio temp3 *= Varm_to_Duty_ratio_Gain; // Output Duty Ratio

Duty_Ratio = temp3; // Gain Block Gain2 Gain2 = temp2 * Gain2_Gain; }

/*

* controller_update - update the controller integrator block */

void controller_update(void) {

// Perform update

// Limited DiscreteIntegrator Block Discrete-Time Integrator // time step of 0.0017 seconds

Discrete_Time_Integrator = Discrete_Time_Integrator + 0.0017 * Gain2; // limit states

if (Discrete_Time_Integrator > Discrete_Time_Integ_US) { Discrete_Time_Integrator = Discrete_Time_Integ_US;

} else if (Discrete_Time_Integrator < Discrete_Time_Integ_LS) { Discrete_Time_Integrator = Discrete_Time_Integ_LS; }

} /*

* pwm_update - set the pwm output to the correct duty ratio for the next interrupt */ void pwm_update(void) { // phase b, non-inverted pwm = 255 * Duty_Ratio; OCR1A = pwm; // phase a, inverted pwm = 255 * (1 - Duty_Ratio); OCR1B = pwm; } /*

* field_update - set the field pwm output to the correct duty ratio for the next interrupt */

{ pwm = 255 * Field_Duty_Ratio; OCR2 = pwm; } void main(void) {

// Declare your local variables here char string[15];

unsigned char pD; double dr;

// Input/Output Ports initialization // Port A PORTA=0x00; DDRA=0x00; // Port B DDRB=0xFF; PORTB=0xFF; // Port C //PORTC=0x00; //DDRC=0x00; DDRC=0xFF; PORTC=0xFF; // Port D PORTD=0x00; DDRD=0xB0; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Output Compare // OC0 output: Disconnected TCCR0=0x00;

TCNT0=0x00;

// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: 8 bit Pulse Width Modulation // OC1A output: Non-Inverted // OC1B output: Inverted // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0xB1; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Pulse Width Modulation // OC2 output: Inverted TCCR2=0x60; ASSR=0x00; TCNT2=0x00; OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x18;

// External Interrupt(s) initialization // INT0: Off

// INT1: Off GIMSK=0x00; MCUCR=0x00;

// UART initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity // UART Receiver: On

// UART Transmitter: On UCR=0x98;

// UART Baud rate: 9600 UBRR=0x19;

// Analog Comparator initialization // Analog Comparator: Off

// Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80;

// ADC initialization

// ADC Clock frequency: 2000.000 kHz ADCSR=0x91;

// Global enable interrupts #asm("sei")

// clear rs232 buffer UDR=0;

// initialise parameters initialise_param();

// start timer1 counter to run on the clock TCCR1B = 0x01;

// start timer2 counter to run on the clock TCCR2 = 0x61;

// initialise the duty ratio to zero

// phase b, on timer1, which has its output non-inverted OCR1A = 0;

// phase a on timer1, inverted OCR1B = 255;

// initialise the field duty ratio to zero OCR2 = 0;

while (1) {

// Start of controller code

// read port d, if not pin 3 (switch 3 not pressed) do nothing, else start pD = PIND;

PORTB = pD;

if (pD != 71) // do nothing

{

// reset everything when pin 6 switch pressed if (pD == 15) { initialise_param(); OCR1A = 0; OCR1B = 255; OCR2 = 0; }

// a/d reading when pin 2 switch pressed if (pD == 75) {

// while switch 6 not pressed

// read the a/d channel 7 and use this value as the duty ratio

PORTB = pD; delay_ms(100); pD = PIND; while (pD != 15) { adval = read_adc(7); dr = adval; Duty_Ratio = dr/1023; pwm_update(); Field_Duty_Ratio = Duty_Ratio; field_update(); pD = PIND; delay_ms(5); } delay_ms(100);

}

} else // start controller

{

PORTB = pD;

delay_ms(500); // while switch on pin 6 not pressed while (pD != 15) {

// get a current reading read_current();

// get the desired torque read_torque();

// calculate the controller block outputs controller_outputs();

// perform update of controller

controller_update();

// update the PWM to the correct duty ratio pwm_update();

pD = PIND;

} // end while pin 6 switch not pressed delay_ms(200);

} // end if not pin 3 switch }; // end while 1

In document Electronics Hobby Circuits (Page 93-100)

Related documents