312 lines
7.1 KiB
C
312 lines
7.1 KiB
C
|
//https://homepages.uni-regensburg.de/~erc24492/PID-Regler/AVR221/IAR/doxygen/main_8c-source.html
|
|||
|
|
|||
|
#include <avr/interrupt.h>
|
|||
|
#include <avr/io.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include "pid.h"
|
|||
|
|
|||
|
#define F_CPU 8000000UL
|
|||
|
|
|||
|
#define BAUD 250000UL
|
|||
|
|
|||
|
#define F_TIMER 80L // Timer1 ISR-Frequenz != 1Hz
|
|||
|
#define T1_PRESCALER 1024 // Hardware-Vorteiler f<>r Timer 1,
|
|||
|
// muss mit der Konfiguratiom <20>bereinstimmen!
|
|||
|
#define OCRx_RELOAD ((F_CPU / (T1_PRESCALER * F_TIMER)) -1) // Periodendauer pro Interrupt
|
|||
|
|
|||
|
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
|
|||
|
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
|
|||
|
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
|
|||
|
|
|||
|
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
|||
|
#error
|
|||
|
#endif
|
|||
|
|
|||
|
#define HEATER_PIN_OUT DDRB |= (1<<PB4);
|
|||
|
#define PUMP_PIN_OUT DDRB |= (1<<PB3);
|
|||
|
|
|||
|
#define HEATER_ON PORTB |= (1<<PB4);
|
|||
|
#define HEATER_OFF PORTB &= ~(1<<PB4);
|
|||
|
#define PUMP_ON PORTB |= (1<<PB3);
|
|||
|
#define PUMP_OFF PORTB &= ~(1<<PB3);
|
|||
|
//MISO = PB6 DO
|
|||
|
//MOSI = PB5 DI
|
|||
|
//CS = PB1
|
|||
|
//SCK = PB7
|
|||
|
#define CS_DIS PORTB |= (1<<PB1);
|
|||
|
#define CS_EN PORTB &= ~(1<<PB1);
|
|||
|
|
|||
|
|
|||
|
#define DMX_BAUD 250000
|
|||
|
#define DMX_LOST_TIMEOUT 8000
|
|||
|
|
|||
|
volatile unsigned int dmx_lost = DMX_LOST_TIMEOUT;
|
|||
|
|
|||
|
volatile unsigned int dmx_adresse = 1;
|
|||
|
volatile unsigned char dmx_buffer[2];
|
|||
|
|
|||
|
//volatile unsigned char led_kanal[3];
|
|||
|
|
|||
|
volatile unsigned long temperature;
|
|||
|
//4500 ca 285<38>C //OFF
|
|||
|
//4400 ca 278<37>C
|
|||
|
//4300 ca 272<37>C
|
|||
|
//4250 ca 270<37>C
|
|||
|
//4200 ca 262<36>C
|
|||
|
// ca 250<35>C //ON
|
|||
|
//3800 ca 238<33>C
|
|||
|
//3500 ca 220<32>C
|
|||
|
//3200 ca 200<30>C
|
|||
|
//2800 ca 175<37>C
|
|||
|
//2500 ca 156<35>C
|
|||
|
//2200 ca 138<33>C
|
|||
|
//1800 ca 115<31>C
|
|||
|
//1400 ca 100<30>C
|
|||
|
//1200 ca 80<38>C
|
|||
|
//570 ca 50<35>C
|
|||
|
//340 ca 25<32>C
|
|||
|
|
|||
|
//KR bei 125V = 520 -> 130 bei 230V
|
|||
|
//P_C ca 90s
|
|||
|
//PWM bei 3670 (275<37>C)
|
|||
|
//heizen 32000 bei DMX-Wert= 32
|
|||
|
|
|||
|
|
|||
|
struct PID_DATA pidData;
|
|||
|
int16_t p_factor = 85; //85
|
|||
|
int16_t i_factor = 0; //1
|
|||
|
int16_t d_factor = 40; //11
|
|||
|
int16_t processValue = 1024; //Ist-Temp
|
|||
|
int16_t setPoint = 4220; //Soll-Temp (275<37>C) 4220
|
|||
|
int16_t Factor = (32767/80);
|
|||
|
volatile int16_t PWM = 0; //16Bit PWM
|
|||
|
volatile uint8_t PUMP = 0; //8Bit PWM
|
|||
|
|
|||
|
volatile int8_t T = 0;
|
|||
|
|
|||
|
void Fehler() {
|
|||
|
cli(); //Interrupts aus
|
|||
|
HEATER_OFF; //Heizung aus
|
|||
|
PUMP_OFF; //Pumpe aus
|
|||
|
while (1) {
|
|||
|
//H<>lt Maschine bei Fehler an
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
long spi()
|
|||
|
{
|
|||
|
//Max31855 einlesen
|
|||
|
unsigned char y = 0;
|
|||
|
unsigned char x = 0;
|
|||
|
long wert;
|
|||
|
CS_EN; //Enable CS
|
|||
|
for(unsigned long tmpa = 0;tmpa<5;tmpa++)asm("nop"); //ca 100ns warten
|
|||
|
|
|||
|
//Byte 1
|
|||
|
USIDR = 0x0;
|
|||
|
USISR = (1<<USIOIF);
|
|||
|
do {
|
|||
|
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
|
|||
|
} while ((USISR & (1<<USIOIF)) == 0);
|
|||
|
x = (unsigned int)USIDR;
|
|||
|
// Byte2
|
|||
|
USIDR = 0x0;
|
|||
|
USISR = (1<<USIOIF);
|
|||
|
do {
|
|||
|
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
|
|||
|
} while ((USISR & (1<<USIOIF)) == 0);
|
|||
|
y = (unsigned int)USIDR;
|
|||
|
|
|||
|
// Byte 3
|
|||
|
USIDR = 0x0;
|
|||
|
USISR = (1<<USIOIF);
|
|||
|
do {
|
|||
|
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
|
|||
|
} while ((USISR & (1<<USIOIF)) == 0);
|
|||
|
//Byte 4
|
|||
|
USIDR = 0x0;
|
|||
|
USISR = (1<<USIOIF);
|
|||
|
do {
|
|||
|
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
|
|||
|
} while ((USISR & (1<<USIOIF)) == 0);
|
|||
|
|
|||
|
CS_DIS; //Disable CS
|
|||
|
|
|||
|
//Pr<50>fen ob Sensor angeschlossen ist
|
|||
|
if (y & 0x01) {Fehler();}
|
|||
|
wert = (unsigned long) (((long)x << 8) | (long)y);
|
|||
|
return wert;
|
|||
|
}
|
|||
|
|
|||
|
void enable_spi(unsigned char speed)
|
|||
|
{
|
|||
|
if (speed) {
|
|||
|
PORTB |= (1<<PB6)|(1<<PB1); // pull-up i.e. disabled
|
|||
|
DDRB |= (1<<PB7)|(1<<PB6)|(1<<PB1);
|
|||
|
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK);
|
|||
|
DDRB &= ~(1<<PB5); //Input: PB6=DI (MOSI)
|
|||
|
PORTB |= (1<<PB5); //interner Pull-up an PA6 aktivieren
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//DMX Empfangen
|
|||
|
ISR (USART_RX_vect)
|
|||
|
{
|
|||
|
static unsigned int dmx_channel_rx_count = 0;
|
|||
|
static unsigned char dmx_valid = 0;
|
|||
|
unsigned char recv = 0;
|
|||
|
|
|||
|
recv = UDR;
|
|||
|
if(UCSRA&(1<<FE))
|
|||
|
{
|
|||
|
if(dmx_channel_rx_count > 1)
|
|||
|
{
|
|||
|
dmx_lost = 0;
|
|||
|
}
|
|||
|
dmx_channel_rx_count = 0;
|
|||
|
dmx_buffer[0] = recv;
|
|||
|
if(dmx_buffer[0] == 0)
|
|||
|
{
|
|||
|
dmx_valid = 1;
|
|||
|
dmx_channel_rx_count++;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dmx_valid = 0;
|
|||
|
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
//Test da DMX einen Fehler geworfen hat
|
|||
|
dmx_valid = 1;
|
|||
|
|
|||
|
if(dmx_valid)
|
|||
|
{
|
|||
|
//PUMP_ON;
|
|||
|
if(dmx_channel_rx_count == dmx_adresse) dmx_buffer[1] = recv;
|
|||
|
|
|||
|
if(dmx_channel_rx_count < 514)
|
|||
|
{
|
|||
|
dmx_channel_rx_count++;
|
|||
|
}
|
|||
|
//PUMP_OFF;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ISR (TIMER0_COMPA_vect)
|
|||
|
{
|
|||
|
static unsigned char pwm_counter = 0;
|
|||
|
|
|||
|
pwm_counter++;
|
|||
|
if(pwm_counter == 255)
|
|||
|
{
|
|||
|
pwm_counter = 0;
|
|||
|
}
|
|||
|
|
|||
|
if(dmx_lost<DMX_LOST_TIMEOUT)
|
|||
|
{
|
|||
|
dmx_lost++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ISR (TIMER1_COMPA_vect) {
|
|||
|
OCR1A = OCRx_RELOAD; //Timer neu laden
|
|||
|
if (T == 80) {
|
|||
|
int16_t z;
|
|||
|
|
|||
|
//St<53>rgr<67><72>enaufschaltung bei niedriger Temperatur
|
|||
|
if (temperature < 4300) {
|
|||
|
if (PUMP < 32) {z = PUMP * 1024;} else {z = 32767;}; //Pumpenleistung bestimmen
|
|||
|
} else {z = 0;}; //Bei kleinerer temperatur wird St<53>rgr<67><72>e aufgeschaltet //32 entspricht 32000 sollleistung
|
|||
|
|
|||
|
PWM = pid_Controller(setPoint, temperature, z, &pidData); //SetPoint = tsoll, processValue = tist errorValue = Pumpenleistung
|
|||
|
T=0;
|
|||
|
}
|
|||
|
T++; //PWM mit 80 schritten
|
|||
|
//Heizung schalten
|
|||
|
if (T < (PWM / Factor)) {HEATER_ON;} else {HEATER_OFF;};
|
|||
|
|
|||
|
//Pumpe mit PWM einschalten, falls temperatur > 250<35> und kleiner 300<30>C
|
|||
|
if (T < (PUMP / 4) && (temperature > 4000) && (temperature < 4500)) {PUMP_ON;} else {PUMP_OFF;};
|
|||
|
}
|
|||
|
|
|||
|
//Hauptprogramm
|
|||
|
int main (void)
|
|||
|
{
|
|||
|
//Init usart
|
|||
|
|
|||
|
UBRRH = UBRR_VAL >> 8;
|
|||
|
UBRRL = UBRR_VAL & 0xFF;
|
|||
|
|
|||
|
UCSRB|=(1 << RXEN | 1<< RXCIE);
|
|||
|
UCSRC|=(1<<USBS);
|
|||
|
//Inputs setzen
|
|||
|
DDRD &= ~(1 << PD6); // switch input pin
|
|||
|
PORTD |= (1 << PD6); // enable pull-up resistor
|
|||
|
DDRB &= ~(1 << PB2); // switch input pin
|
|||
|
PORTB |= (1 << PB2); // enable pull-up resistor
|
|||
|
DDRD &= ~(1 << PD5); // switch input pin
|
|||
|
PORTD |= (1 << PD5); // enable pull-up resistor
|
|||
|
DDRD &= ~(1 << PD4); // switch input pin
|
|||
|
PORTD |= (1 << PD4); // enable pull-up resistor
|
|||
|
DDRD &= ~(1 << PD3); // switch input pin
|
|||
|
PORTD |= (1 << PD3); // enable pull-up resistor
|
|||
|
DDRD &= ~(1 << PD2); // switch input pin
|
|||
|
PORTD |= (1 << PD2); // enable pull-up resistor
|
|||
|
DDRD &= ~(1 << PD1); // switch input pin
|
|||
|
PORTD |= (1 << PD1); // enable pull-up resistor
|
|||
|
DDRB &= ~(1 << PB0); // switch input pin
|
|||
|
PORTB |= (1 << PB0); // enable pull-up resistor
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//DMX-Adresse einlesen;
|
|||
|
// dmx_adresse = 0;
|
|||
|
if (PINB & (1 << PB0)) dmx_adresse =1;
|
|||
|
if (PIND & (1 << PD6)) dmx_adresse +=128;
|
|||
|
if (PINB & (1 << PB2)) dmx_adresse +=64;
|
|||
|
if (PIND & (1 << PD5)) dmx_adresse +=32;
|
|||
|
if (PIND & (1 << PD4)) dmx_adresse +=16;
|
|||
|
if (PIND & (1 << PD3)) dmx_adresse +=8;
|
|||
|
if (PIND & (1 << PD2)) dmx_adresse +=4;
|
|||
|
if (PIND & (1 << PD1)) dmx_adresse +=2;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//PID Konfigurieren:
|
|||
|
pid_Init(p_factor, i_factor , d_factor , &pidData);
|
|||
|
|
|||
|
// Timer 1 freigeben
|
|||
|
TCCR1B = (1<<WGM12)| (1<<CS12) | (1<<CS10); //Vorteiler 1024
|
|||
|
OCR1A = OCRx_RELOAD;
|
|||
|
// OCR1A Interrupt freigeben, wird f<>r Timer CTC mode benutzt
|
|||
|
TIMSK = 1<<OCIE1A;
|
|||
|
|
|||
|
// DDRD |=(1<<PD2);
|
|||
|
// PORTD &=~(1<<PD2);
|
|||
|
|
|||
|
HEATER_PIN_OUT;
|
|||
|
PUMP_PIN_OUT;
|
|||
|
|
|||
|
enable_spi(1);
|
|||
|
|
|||
|
sei();
|
|||
|
|
|||
|
while(1)
|
|||
|
{
|
|||
|
if(dmx_lost==DMX_LOST_TIMEOUT)
|
|||
|
{
|
|||
|
dmx_buffer[1] = 0;
|
|||
|
};
|
|||
|
PUMP = dmx_buffer[1];
|
|||
|
temperature = spi();
|
|||
|
if (temperature > 4600) Fehler();
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|