diff --git a/main.c b/main.c index f24f306..602a764 100644 --- a/main.c +++ b/main.c @@ -2,24 +2,83 @@ #include #include #include +#include + +#include "buffer.h" -volatile uint16_t holdingRegisters[4]; void modbusGet(void); +volatile buffer_t adc_buf[4]; +volatile float adc_avrg[4]; + +volatile float output; +volatile struct pid controller; + +volatile float setpoint_1 = 180 * 102 / 34; +volatile float setpoint_2 = 150 * 102 / 34; +volatile float setpoint_3 = 150 * 102 / 34; + +struct pid { + // Controller gains + float kP; + float kI; + float kD; + + // State variables + float lastError; + float integral; +}; + +float pid_step(volatile struct pid* controller, float dt, float error) { + // Calculate p term + float p = error * controller->kP; + + // Calculate i term + ATOMIC_BLOCK(ATOMIC_FORCEON){ + controller->integral += error * dt * controller->kI; + if(controller->integral > 80) + controller->integral = 80; + if(controller->integral < -80) + controller->integral = -80; + } + + // Calculate d term, taking care to not divide by zero + float d = dt == 0 ? 0 : ((error - controller->lastError) / dt) * controller->kD; + controller->lastError = error; + + return p + controller->integral + d; +} + +void initADC(void) +{ + ADMUX = 1 << REFS0 | 0 << REFS1; //Select external Vref + + //ADC Status Register A + ADCSRA = 1 << ADEN //Enable ADC + | 1 << ADIE //Enable ISR after conversion complete + //| 1< 128) + output = 128; + + if(output >= 1){ + uint32_t tmp = output * 512; + if(tmp >= 0x10000) + tmp = 0xFFFE; + + OCR1A = tmp; + PORTB |= 0x0E; + } + else + OCR1A = 1000; + + + //if(adc_avrg[0] < 99 && !(PORTB & 0x01)) + // PORTB |= 1 << 0; + //if(adc_avrg[0] > 99 && (PORTB & 0x01)) + // PORTB &= ~(1 << 0); +} +ISR(TIMER1_COMPA_vect) { + PORTB &= ~(0x0E); +} + +ISR(ADC_vect) +{ + static uint8_t init[4] = {0,0,0,0}; + static uint8_t current_channel = 0; + + //Reading 10bit conversion result + uint16_t ADC_reading = ADCL; //copy the first LSB bits + ADC_reading |= ADCH << 8; //copy remaing byte + ADC_reading *= 10; + insert_to_buffer(ADC_reading, &adc_buf[current_channel]); + + if(adc_buf[current_channel].position == BUFFER_SIZE-1){ + if(init[current_channel]){ + float tmp = 99*adc_avrg[current_channel]; + tmp += get_buffer_mean(&adc_buf[current_channel])/30; + adc_avrg[current_channel] = tmp/100; + } + else{ + adc_avrg[current_channel] = get_buffer_mean(&adc_buf[current_channel])/30; + init[current_channel]=0; + } + } + + current_channel++; + if(current_channel == 4) + current_channel = 0; + set_ADC_Channel(current_channel); + + + ADCSRA |= (1 << ADSC); //Start next conversion +} + diff --git a/makefile b/makefile index de07855..947663f 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ TARGET = main -FILES = main modbus +FILES = main modbus buffer MCU = atmega328p PROGC = m328p CC = avr-gcc