Gast
#35428
Hallo, ich möchte eigentlich eine ganz simple Sache machen, aber
irgendwie funzt es nicht:
Um das Regelverhalten meines Ventils beurteilen zu können, möchte ich
Sollwert und Istwert über das komplette Spektrum auftragen. D.h. ich
erhöhe kontinuierlich den Sollwert (kann Werte zwischen 0 und 1023
annehmen) und sehe mir dazu die Istwerte an. Geregelot wird jedes mal
wenn ein Interrupt aufgerufen wird in der ISR. Am Ende meiner ISR erhöhe
ich meine globale Variable j um 1, jedes mal wenn j den Wert 100
erreicht, wird mein Sollwert um 1 erhöht und j wieder zurück auf Null
gesetzt. Unabhängig davon, ob ich j als static oder volatile definiere
funktioniert die ganze Sache nicht. Wißt ihr woran das liegen könnte
oder habt ihr eine bessere Lösung? Hier das Programm:
/*********************************************
Project : Programm zur Beurteilung des Regelverhaltens: v_soll wird
kontinuierlich erhöht und v_ist entsprechend auf dem Terminal
ausgegeben.
Chip type : ATmega323
Program type : Application
Clock frequency : 3.686400 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 512
*********************************************/
#include <mega323.h>
// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSR|=0x40;
// Wait for the AD conversion to complete
while ((ADCSR & 0x10)==0);
ADCSR|=0x10;
return ADCW;
}
unsigned int v_ist;
int e_k; // Regelabweichung
int e_k_alt;
float k_p =1; // 1.446 Verstärkungsfaktor
int u_p; // Stellgröße
int u_p_alt;
unsigned int v_soll;
int stell;
char istwert[4];
static int j;
// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// aktuelle Spannung einlesen (Wert zwischen 0 und 1023):
v_ist = read_adc(0);
// Regelabweichung e_k berechnen:
e_k = v_soll - v_ist;
// P-Regler (mit "gleitendem" Offset v_soll)
u_p = e_k * k_p + v_soll;
// Stellgrößenbegrenzung:
if (u_p > 600) u_p = 600;
else if (u_p < 400) u_p = 400;
// Stellgröße in entsprechenden PWM Wert umrechnen:
stell = (int) u_p;
// Pulsbreite setzen:
OCR1A = stell;
u_p_alt = u_p;
e_k_alt = e_k;
itoa(read_adc(0),istwert);
puts(istwert);
// Laufvariable j um 1 erhöhen:
j++;
}
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTA=0x00;
DDRA=0x00;
// Port B initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out
Func7=Out
// State0=1 State1=1 State2=1 State3=1 State4=1 State5=1 State6=1
State7=1
PORTC=0xFF;
DDRC=0xFF;
/// Port D initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=Out Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=0 State6=T
State7=T
PORTD=0x00;
DDRD=0x20;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value:
// TCCR1B=0x04: 4.400 kHz/ 2046 = 7 Hz
// TCCR1B=0x01: 3686.400 kHz/2046 = 1800 Hz
// Mode: Ph. correct PWM top=03FFh
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x83;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: TCCR2=0x07: 3600 Hz -> t_0 = 1/(3600/255) = 70.83 ms
// TCCR2=0x06; 14400 Hz -> t_0 = 1/(14400/255) = 17,708 ms
// TCCR2=0x05; 28800 Hz -> t_0 = 1/(28800/255) = 8,85 ms
// TCCR2=0x02; 460800 Hz -> t_0 = 1/(460800/255) = 0,553 ms
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 115200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC Clock frequency: 115,200 kHz => T=1/f=1/115200 Hz = 0,00868 ms
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSR=0x85;
// Global enable interrupts
#asm("sei")
// ################## PROGRAMMSTART ######################
// zum Starten des Programmas wird das Zeichen "s" eingelesen:
if (getchar() == 's')
{
// Timer 2 der die Interrupts auslöst loslaufen //lassen:
TCCR2=0x05;
// bis v_soll seinen Maximalwert 1023 erreicht hat,
//folgendes tun:
while (v_soll < 1024)
{
// jedes mal wenn j den Wert 100 erreicht hat,
// wird der Sollwert um 1 erhöht:
if (j == 100)
{
v_soll += 1;
// j wieder zurücksetzen
j = 0;
}
}
}
}