-
Notifications
You must be signed in to change notification settings - Fork 0
/
toimivakoodi3.txt
238 lines (190 loc) · 5.28 KB
/
toimivakoodi3.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
* GccApplication2.c
*
* Created: 3.4.2019 14.27.12
* Author : tapioj
*/
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/cpufunc.h>
#define BAUD 9600
#define BAUDRATE (F_CPU/(16UL*BAUD)-1)
typedef enum { false, true } bool;
//Vaiheet:
// vastaanotetaan luku (0-5) sarjaväylän kautta
// asetetaan oikea jännite PWM:n avulla tiettyyn pinniin
// arvo duty_cycle osuus 256:sta 8-bit binary
// 0 0 0 00000000
// 1 20 51 00110011
// 2 40 102 01100110
// 3 60 153 10011001
// 4 80 204 11001100
// 5 100 255 11111111
// mitataan jännitettä AD-muuntimen avulla ja pidetään se vakaana muuttamalla PWM-arvoa kuorman muuttuessa
// Lähetetään PWM-arvo sarjaväylän kautta tietokoneelle
// napin painallus aiheuttaa keskeytyksen, jolloin ulostulojännite asetetaan nollaan (järjestelmä seisahtuu)
// uusi painallus jatkaa toimintaa siitä mihin jäätiin
//suoraan harkka 7 mallivastauksesta
void initADC(void)
{
// init AD channel 0
// disable channel 0 input buffer
DIDR0 |= 0x01;
// write 1 to corresponding output pin
PORTC |= 0x01;
// choose channel 0, ADMUX[MUX3:MUX0] -> 0b0000
// default is OK
// choose internal Vcc reference, ADMUX[REFS1:REFS0] -> 0b01
ADMUX |= (1<<REFS0);
// use only high byte ADCSRA[ADLAR] -> 1
// ADMUX |= (1<<ADLAR);
// clock prescaler 128, ADCSRA [ADPS 2:0] -> 0b111
ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
// enable AD-converter in Power Reduction Register, PRR[PRADC] -> 0
PRR &= ~(1<<PRADC);
// enable AD-converter in ADCSRA
ADCSRA |= (1<<ADEN);
}
uint16_t readADC8(void)
{
uint16_t vtmp;
// start conversion ADCSRA[ADSC] -> 1
ADCSRA |= (1<<ADSC);
// poll ADCSRA[ADSC] -> 1
while (ADCSRA & (1<<ADSC)) ;
// read the 8 low order bits
vtmp = ADCL;
// read the 2 high order bits and shift them up
return vtmp + ((uint16_t)ADCH<<8);
}
void setup_pwm(uint8_t duty_cycle){
//init D5 as output
DDRD |=(1<<PD5);
PORTD|=(1<<PD5);
//init OCR0B as compare match
TCCR0A|=(1<<COM0B1|1<<WGM00|1<<WGM01);
//PWM frequency 250 kHz
TCCR0B |=(1<<CS00)|(1<<CS01);
// set pwm duty cycle
OCR0B = duty_cycle;
}
///UARTia varten koodinpätkä
void init_UART(unsigned short uValue ){
// setting the baud rate based on the datasheet
UBRR0H =(BAUDRATE>>8);//(unsigned char) ( uValue>> 8); // 0x00
UBRR0L = BAUDRATE;//(unsigned char) uValue; // 0x0C
// enabling TX & RX
UCSR0B = (1<<RXEN0)|(1<<TXEN0);//enable receiver and transmitter
//UCSR0A = (1<<UDRE0)|(1<<U2X0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Set frame: 8data, 1 stop
}
volatile uint8_t dPortInput; // read contents of the D port
volatile uint16_t edgeCounter = 0; // count of the rising edges of the signal in D0
uint8_t d0Input = 0; // state of D0
uint8_t previousState = 0; // previous state of D0
ISR(PCINT2_vect) // Pin change interrupt flag register PCIFR (0x3b)
{
d0Input = PIND & (1<<PD7); // read port D pin 0 (mask all other bits)
if(previousState==0) { // if previous state was 0 then the change must be a rising edge
// action
dPortInput = PIND; // read port D to the buffer variable
edgeCounter++; // count rising edges
}
previousState=d0Input;
}
uint8_t voltage = 0;
ISR(USART_RX_vect){
voltage = UDR0;
}
// unsigned char UART_Receive( void )
// {
// /* Wait for data to be received */
// while ( !(UCSR0A & (1<<RXC0)) )
// ;
// /* Get and return received data from buffer */
// return UDR0;
// }
void UART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}
bool program_running = true;
//
// }
//
//
// }
int main(void)
{
uint8_t duty_cycle = 0b00000000;
init_UART(BAUD);
setup_pwm(duty_cycle);
/*DDRB |= _BV(DDB5);*/
int16_t error = 0;
int16_t previous_error = 0;
int16_t integral = 0;
int16_t derivative = 0;
int16_t output = 0;
int16_t measured_voltage = 0;
while(program_running)
{
UART_Transmit(voltage);
//TODO:: Please write your application code
switch (voltage){
case 0:
duty_cycle = 0b00000000;
break;
case 1:
duty_cycle = 0b00110011;
break;
case 2:
duty_cycle = 0b01100110;
break;
case 3:
duty_cycle = 0b10011001;
break;
case 4:
duty_cycle = 0b11001100;
break;
case 5:
duty_cycle = 0b11111111;
break;
OCR0B = duty_cycle;
}
/*PORTB ^= _BV(PD5);*/
// _delay_ms(500);
// setup_pwm(PD5);
// init_UART(MYUBRR);
// DDRD |= (1<< PD7);
// for(;;){
// PORTD ^= (1<< PD7);
// UART_Transmit('x');
// UART_Transmit('l');
// //_delay_ms(1000);
#define DT 1 //ms
#define KP 2 //P Factor
#define KI 3 // I Factor
#define KD 4 // D Factor
#define TARGET_VOLTAGE
measured_voltage = read_voltage_sensor();
error = TARGET_VOLTAGE - measured_voltage;
integral = integral + (error*DT);
derivative = (error - previous_error)/DT;
output =(KP*error) +(KI*integral) +(KD*derivative);
set_output_pwm(output);
previous_error = error;
_delay_ms(DT);
}
return 0;
}