-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
348 lines (261 loc) · 9.63 KB
/
main.c
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
* File: main.c
* Author: Shankar Ramharack
* UWI ID: 816019096
* Created on July 17, 2021, 5:07 PM
*/
// CONFIG1
#pragma config FEXTOSC = XT // External Oscillator mode selection bits->XT (crystal oscillator) above 500kHz, below 4MHz; PFM set to medium power
#pragma config RSTOSC = EXT1X // Power-up default value for COSC bits->EXTOSC operating per FEXTOSC bits
#pragma config CLKOUTEN = OFF // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled
// CONFIG2
#pragma config MCLRE = ON // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = OFF // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset
#pragma config DEBUG = OFF // Background Debugger->Background Debugger disabled
// CONFIG3
#pragma config WDTCPS = WDTCPS_31 // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7 // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC // WDT input clock selector->Software Control
// CONFIG4
#pragma config WRT = OFF // UserNVM self-write protection bits->Write protection off
#pragma config SCANE = available // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.
// CONFIG5
#pragma config CP = OFF // UserNVM Program memory code protection bit->Program Memory code protection disabled
#pragma config CPD = OFF // DataNVM code protection bit->Data EEPROM code protection disabled
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>
#define _XTAL_FREQ 2000000
#define Baud_rate 1200
#define DPSW0 RA0
#define DPSW1 RA1
#define DPSW2 RA2
#define DPSW3 RA3
#define ECHO RB4
#define TRIG RB3
#define OC_LEC RB2 //LED for optical encoder
#define LDRI0 RB1
#define LDRI1 RB0
/* ============|
* SERIAL COMS |
* ============|
*/
void cfg_eusart(void)
{
TRISCbits.TRISC6 = 0; // configuring pin 6 on port c as output
ANSELCbits.ANSC6 = 0; // configuring pin 6 on port c as digital output
RC6PPS = 0x10; // configuring pin 6 on port c for
// serial transmission(TX)
SP1BRGH = 0x00; // setting lower reg to 0
SP1BRGL = 0b00011001; // Setting baud rate of 1200
BAUD1CONbits.BRG16 = 0; // configuring BRG for 8-bit mode
TX1STAbits.BRGH = 0; // configures BRG for low baud rate
TX1STAbits.SYNC = 0; // configures EUSART for async. transmission
RC1STAbits.SPEN = 1; // enables serial port
TX1STAbits.TXEN = 1; // enables serial transmission
TX1STAbits.TX9 = 0; // disables 9 bit transmission
}
void cfg_pwm(void)
{
TRISAbits.TRISA0 = 1;
TRISAbits.TRISA1 = 1;
TRISAbits.TRISA2 = 1;
TRISAbits.TRISA3 = 1;
ANSELAbits.ANSA0 = 0;
ANSELAbits.ANSA1 = 0;
ANSELAbits.ANSA2 = 0;
ANSELAbits.ANSA3 = 0;
TRISBbits.TRISB5 = 0;
ANSELBbits.ANSB5 = 0;
RB5PPS = 0x0A; //Routing CCP2 peripheral to pin 5 on port b
CCP2CON = 0x9F;
CCPTMRS0 = 0x05;
PR2 = 19;
CCPR2L = 0xFF;
CCPR2H = 0xFF;
T2CLKCON = 0x01;
T2CON = 0xF0;
}
void send_char(char word){
while(!TXIF);
TXREG = word;
}
void send_string(char* st_pt)
{
while(*st_pt)
send_char(*st_pt++);
}
/* ===========================
* ULTRASONIC DISTANCE SENSOR
* ============================
*
*/
void ranging_sys_init(void){
// configuring IO pins for ranging(orientation included)
TRISBbits.TRISB4 = 1; // ECHO pin - input
TRISBbits.TRISB3 = 0; // TRIG pin - output
TRISBbits.TRISB2 = 0; // LED on encoder - output
TRISBbits.TRISB1 = 1; // LDR0 - input
TRISBbits.TRISB0 = 1; // LDR1 - input
ANSELB = 0x00; // all pins on port b are digital
LATBbits.LATB2 = 1;
T0CON0bits.T0EN = 0; // Disabling TMR0
T0CON0bits.T016BIT = 1; // configuring TMR0 for 16 bit operation
T0CON0bits.T0OUTPS = 0b0000; // setting TMR0 pre-scaler to none
T0CON1bits.T0CS = 0b010; // selecting Fosc/4 as clk source
T0CON1bits.T0ASYNC = 1; // configuring TMR0 for async operaiton
T0CON1bits.T0CKPS = 0b0001; // setting TMR0 post-scaler as 1:2
}
int calcAngle(void)
{
int angle = 0;
//LDRI0 is the inner photo resistor
if(!(LDRI0 == 1) && !(LDRI1 == 0))
{
//90 deg
angle = 90;
}
else if(!(LDRI0 == 1) && !(LDRI1 == 1))
{
//180 deg
angle = 180;
}
else if(!(LDRI0 == 0) && !(LDRI1 ==1))
{
//270deg
angle = 270;
}
else
{
//0 or 360deg or error
angle = 0;
}
return angle;
}
char *itoa(int value)
{
static char buffer[12]; // using 12 bytes to hold int32 dtype
int original = value; // save original value
int c = sizeof(buffer)-1;
buffer[c] = 0; // write null char at the end
if (value < 0) // if it's negative, note that and take the absolute value
value = -value;
do // write least significant digit of value that's left
{
buffer[--c] = (value % 10) + '0';
value /= 10;
} while (value);
if (original < 0)
buffer[--c] = '-';
return &buffer[c];
}
int distance = 0; // for storing distance
/*
* =====================
* PWM BLDC FAN CONTROL
* ======================
*
*/
void set_pwm_dc(uint8_t dc)
{
if(dc>20)
{
CCPR2H = 20;
//CCPR2L = 0XFF;
}
else if(dc <= 0)
{
CCPR2H = 0;
//CCPR2L = 0;
}
else{
CCPR2H = dc;
//CCPR2L = 0XFF;
}
}
uint8_t dpsw_to_dc(void)
{
//converts the switch combination from 4DIP-SW to a duty cycle value between 0-20
int d0;
int d1;
int d2;
int d3;
if(DPSW0){d0 = 1000;} else {d0 = 0;}
if(DPSW1){d1 = 100;} else {d1 = 0;}
if(DPSW2){d2 = 10;} else {d2 = 0;}
if(DPSW3){d3 = 1;} else {d3 = 0;}
int binary_d = d0 + d1 + d2 + d3;
if(binary_d == 0)
{
return 0;
}
uint8_t num_base = 1;
uint8_t rem = 0;
uint8_t decimal_num = 5; //offset to allow reaching max speed at 0b1111
while ( binary_d > 0)
{
rem = binary_d % 10; /* divide the binary number by 10 and store the remainder in rem variable. */
decimal_num = decimal_num + rem * num_base;
binary_d = binary_d/ 10; // divide the number with quotient
num_base = num_base * 2;
}
return decimal_num;
}
void main(void){
//Configuring the EUSART
cfg_eusart();
cfg_pwm();
ranging_sys_init();
// INTEGRATION TEST
__delay_ms(1000); // to avoid corrupted characters in serial tx
send_string("[*]Serial Connection successful\r\n");
uint8_t dc = 0; //duty cycle
while(1)
{
set_pwm_dc(dpsw_to_dc());
TMR0H = 0; //Sets the Initial Value of Timer
TMR0L = 0; //Sets the Initial Value of Timer
T0CON1bits.T0CKPS = 0b0001; //Resetting post scaler since TMR0L write clears it
PORTBbits.RB3 = 1; //TRIGGER HIGH
__delay_us(10); //10uS Delay
PORTBbits.RB3 = 0; //TRIGGER LOW
while(!PORTBbits.RB4); //Waiting for Echo
T0CON0bits.T0EN = 1; //Timer Starts
while(PORTBbits.RB4); //Waiting for Echo goes LOW
T0CON0bits.T0EN = 0; //Timer Stops
distance = (TMR0L | (TMR0H<<8)); //Reads Timer Value
//a = a*0.068
distance = distance*17/250; //Converts Time to Distance and avoids conversion error
distance = distance + 1; // Offset obtained via calibration
dc = CCPR2H; // duty cycle
if(distance>=2 && distance<=400) //Check whether the result is valid or not
{
send_string("Distance = ");
send_string(itoa(distance));
send_string(" cm");
send_string("\tAngle = ");
send_string(itoa(calcAngle()));
send_string(" deg");
//__delay_ms(1000);
send_string("\tPWM Duty Cycle = ");
send_string(itoa(dc));
send_string("\r\n");
}
else
{
send_string("Out of Range\r\n");
}
__delay_ms(400);
}
return;
}