|
|
View previous topic :: View next topic |
Author |
Message |
Srig007 Guest
|
Help with Table |
Posted: Wed Jun 13, 2007 12:25 pm |
|
|
Hi All,
Currently I am working on a small program which takes three inputs from the ADC and immediately output the result obtained by the ADC to the PWM. I am trying to utilize three ADC channels because I have three temperature sensors that I want to control and then output the result to three separate FAN using PWM. Based on the reading of the ADC I want to either increase or decrease the revolution of the fan. Instead of using multiple If statements, I want to have all of the data logged into the lookup table and then just have three if statements one for each ADC-PWM values to control the fan. I know this is possible. My question is how to access the values that I have in each separate lookup table (Store_X, Store_Y, and Store_Z), and compare it to the value I receive from the ADC.
Here is what I have thus far, I have compiled the code but it gives me many syntax errors that I cannot fix. Any help with this is greatly appreciated, thanks.
--Srig
Code: | [size=18]#include <18F6520.h>
#device Adc = 10 //Number of bits the ADC will return is 10 bits
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock = 20000000) //Using 20Mhz External Crystal
//Function Declaration
Void init_ADC0(void);
Void init_ADC1(void);
Void init_ADC2(void);
void main()
{
int16 result_X, result_Y, result_Z, i;
Setup_ADC_PORTS( ALL_ANALOG);
Setup_ADC(ADC_CLOCK_DIV_16);
Setup_CCP1(CCP_PWM); //X
Setup_CCP2(CCP_PWM); //Y
Setup_CCP3(CCP_PWM); //Z
While(1)
{
Init_ADC0(); //Reading ADC0
result_X = read_Adc(); //Storing the value of the Read input to result0
delay_ms(10);
Init_ADC1(); //Reading ADC1
result_Y = read_ADC(); //Storing the value of the Read input to result1
delay_ms(10);
Init_ADC2(); //Reading ADC2
result_Z = read_ADC(); //Storing the value of the Read input to result2
delay_ms(10);
For(I = 0, I <= 10, I++)
{
if(ResultX = Store_X[i] ) //Comparing Result_X
{
setup_PWM1_Duty( Store_X[i][1]); /
delay_ms(10);
}
else
{
Setup_PWM1_Duty(0); //Turn Off the Fan
delay_ms(10);
}
if(ResultY = Store_Y[i]) //Comparing Result_Y
{
setup_PWM2_Duty( Store_Y[i][1] );
delay_ms(10);
}
else
{
Setup_PWM2_Duty(0); //Turn Off the fan
delay_ms(10);
}
if(ResultZ = Store_Z[i]) //Comparing result_Z
{
setup_PWM3_Duty(Store_Z[i][1]);
delay_ms(10);
}
else
{
setup_PWM3_Duty(0);
delay_ms(10);
}
}
// Setup_PWM1_Duty(result_x); //Sending PWM to X
// Setup_PWM2_DUTY(result_y); //Sending PWM to Y
// setup_PWM3_Duty(result_Z); //Sending PWM to Z
delay_ms(10);
}
}
/****************************************************************/
/******************* Changing the ADC Channel *******************/
Void init_ADC0(void) //Setting up the ADC Channel0 //
{ //
Setup_Adc_Channel(0); //
delay_us(20); //
//
} //
//
Void init_ADC1(void) //Setting up the ADC Channel1 //
{ //
Setup_Adc_Channel(1); //
delay_us(20); //
//
} //
//
Void init_ADC2(void) //Setting up the ADC Channel2 //
{ //
Setup_Adc_Channel(2); //
delay_us(20); //
//
} //
/****************************************************************/
Const int16 Store_X [10][1] = {1, 10 //ADC VALUE = 1, PWM OUTPUT = 10
,2, 45 //ADC VALUE = 2, PWM OUTPUT = 45
,3, 50 //ADC VALUE = 3, PWM OUTPUT = 50
,10, 100 //ADC VALUE = 10, PWM OUTPUT = 100
,15, 125 //ADC VALUE = 15, PWM OUTPUT = 125
,25, 250 //ADC VALUE = 25, PWM OUTPUT = 250
,35, 300 //ADC VALUE = 35, PWM OUTPUT = 300
,40, 350 //ADC VALUE = 40, PWM OUTPUT = 350
,50, 500 //ADC VALUE = 50, PWM OUTPUT = 500
,75, 600 //ADC VALUE = 75, PWM OUTPUT = 600
,100, 1023 //ADC VALUE = 100, PWM OUTPUT = 1023
};
Const int16 Store_Y [10][1] = {1, 10 //ADC VALUE = 1, PWM OUTPUT = 10
,10, 45
,45, 50
,50, 100
,65, 200
,75, 300
,90, 400
,100, 550
,125, 650
,325, 1000
,400, 1023 //ADC VALUE = 400, PWM OUTPUT = 1023
};
Const int16 Store_Z [10][1] = {4, 25 //ADC VALUE = 4, PWM OUTPUT = 25
,20, 75
,45, 100
,50, 200
,85, 225
,122, 350
,175, 500
,325, 550
,487, 600
,650, 750
,750, 1023 //ADC VALUE = 750, PWM OUTPUT = 1023
};[/size] |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 13, 2007 3:58 pm |
|
|
You have a few undeclared variables, you have mis-spelled several
CCS function names, and you are using commas instead of semi-colons
in some places. You need to study C and then go through the program
and clean up all these problems. |
|
|
Srigopal007
Joined: 13 Jun 2005 Posts: 11
|
|
Posted: Thu Jun 14, 2007 7:33 am |
|
|
Thanks for pointing these mistakes out, I had gone back to the compiler manual and fixed the necessary mistakes. Can you please help me with accessing the values that I have in each separate lookup table (Store_X, Store_Y, and Store_Z), and compare it to the value I receive from the ADC.
Here is the modified code. Any help on this is greatly apprciated, thanks.
-Srig
Code: | #include <18F6520.h>
#device Adc = 10 //Number of bits the ADC will return is 10 bits
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock = 20000000) //Using 20Mhz External Crystal
//Function Declaration
Void init_ADC0(void);
Void init_ADC1(void);
Void init_ADC2(void);
void main()
{
int16 result_X, result_Y, result_Z, i;
Setup_ADC_PORTS(ALL_ANALOG);
Setup_ADC(ADC_CLOCK_DIV_32);
Setup_CCP1(CCP_PWM); //X
Setup_CCP2(CCP_PWM); //Y
Setup_CCP3(CCP_PWM); //Z
While(1)
{
Init_ADC0(); //Reading ADC0
result_X = read_Adc(); //Storing the value of the Read input to result0
delay_ms(10);
Init_ADC1(); //Reading ADC1
result_Y = read_ADC(); //Storing the value of the Read input to result1
delay_ms(10);
Init_ADC2(); //Reading ADC2
result_Z = read_ADC(); //Storing the value of the Read input to result2
delay_ms(10);
For(I = 0; I <= 10; I++)
{
if(Result_X = Store_X[i] ) //Comparing Result_X
{
Set_PWM1_Duty( Store_X[i][1]); /
delay_ms(10);
}
else
{
Set_PWM1_Duty(0); //Turn Off the Fan
delay_ms(10);
}
if(Result_Y = Store_Y[i]) //Comparing Result_Y
{
set_PWM2_Duty( Store_Y[i][1] );
delay_ms(10);
}
else
{
Set_PWM2_Duty(0); //Turn Off the fan
delay_ms(10);
}
if(Result_Z = Store_Z[i]) //Comparing result_Z
{
set_PWM3_Duty(Store_Z[i][1]);
delay_ms(10);
}
else
{
set_PWM3_Duty(0);
delay_ms(10);
}
}
// Set_PWM1_Duty(result_x); //Sending PWM to X
// Set_PWM2_DUTY(result_y); //Sending PWM to Y
// set_PWM3_Duty(result_Z); //Sending PWM to Z
delay_ms(10);
}
}
/****************************************************************/
/******************* Changing the ADC Channel *******************/
Void init_ADC0(void) //Setting up the ADC Channel0 //
{ //
Setup_Adc_Channel(0); //
delay_us(20); //
//
} //
//
Void init_ADC1(void) //Setting up the ADC Channel1 //
{ //
Setup_Adc_Channel(1); //
delay_us(20); //
//
} //
//
Void init_ADC2(void) //Setting up the ADC Channel2 //
{ //
Setup_Adc_Channel(2); //
delay_us(20); //
//
} //
/****************************************************************/
Const int16 Store_X [10][1] = {1, 10 //ADC VALUE = 1, PWM OUTPUT = 10
,2, 45 //ADC VALUE = 2, PWM OUTPUT = 45
,3, 50 //ADC VALUE = 3, PWM OUTPUT = 50
,10, 100 //ADC VALUE = 10, PWM OUTPUT = 100
,15, 125 //ADC VALUE = 15, PWM OUTPUT = 125
,25, 250 //ADC VALUE = 25, PWM OUTPUT = 250
,35, 300 //ADC VALUE = 35, PWM OUTPUT = 300
,40, 350 //ADC VALUE = 40, PWM OUTPUT = 350
,50, 500 //ADC VALUE = 50, PWM OUTPUT = 500
,75, 600 //ADC VALUE = 75, PWM OUTPUT = 600
,100, 1023 //ADC VALUE = 100, PWM OUTPUT = 1023
};
Const int16 Store_Y [10][1] = {1, 10 //ADC VALUE = 1, PWM OUTPUT = 10
,10, 45
,45, 50
,50, 100
,65, 200
,75, 300
,90, 400
,100, 550
,125, 650
,325, 1000
,400, 1023 //ADC VALUE = 400, PWM OUTPUT = 1023
};
Const int16 Store_Z [10][1] = {4, 25 //ADC VALUE = 4, PWM OUTPUT = 25
,20, 75
,45, 100
,50, 200
,85, 225
,122, 350
,175, 500
,325, 550
,487, 600
,650, 750
,750, 1023 //ADC VALUE = 750, PWM OUTPUT = 1023
}; |
|
|
|
RossJ
Joined: 25 Aug 2004 Posts: 66
|
|
Posted: Thu Jun 14, 2007 8:56 am |
|
|
Hi Srig,
A few things stand out which you should consider...
1. Your lookup tables are incorrectly dimensioned as 10 x 1 instead of 11 x 2. The dimension is the number of items, even though you access them using index values of 0-10 and 0-1.
2. When you are searching the table, your if statement uses '=' instead of '=='. So you are attempting to perform an assignment instead of a comparison. A better solution would be '<', since this would deal with the range of ADC values between the table entries. This works because your table is sorted.
3. You should access 2 dimensional arrays using two indexes, you do 'Store_Y[i]' which returns a pointer to 'Store_Y[i][0]'. If you want the actual value, you must do 'Store_Y[i][0]'.
4. In the for loops you might consider using (sizeof(Store_Y) / 4) so you avoid coding the size of your arrays in multiple places (which is prone to error). If you don't understand how the sizeof() function works, it's in the manual.
/Ross. |
|
|
Srigopal007
Joined: 13 Jun 2005 Posts: 11
|
|
Posted: Thu Jun 14, 2007 11:24 am |
|
|
thanks RossJ and PCM programmer for your great advise,
I always tend to make silly mistakes like the ones you pointed out. I pretty sure that the sizeof(Store_Y)/4) expression will make things easier and error-free, but I have read it but was not able to get as much info on why it is used nor what errors I can potentially get myself into if I did not use it.
I would like to ask some questions since I am trying to implement ADC into my design. I know that there are certain crucial parameters in designing an ADC system, and that is to select the appropriate reference voltage for the device. I do not want to damage the microcontroller by setting a reference voltage that is below the actual operating voltage of the temperature sensor, nor do I want to select a reference voltage that is too high. What and how do I select the appropriate voltage reference for the ADC? Also since I am using the PIC18F6520 microcontroller, do I simply connect the reference voltage to the RA3 pin?
Here is what I have changed based on the recommendations from Ross. Can you please check to see if I have fixed the errors correctly. thanks
--Srig
Fix to Question 1:
Code: | Const int16 Store_Y [11][2] = {1, 10 //ADC VALUE = 1, PWM OUTPUT = 10
,10, 45
,45, 50
,50, 100
,65, 200
,75, 300
,90, 400
,100, 550
,125, 650
,325, 1000
,400, 1023 //ADC VALUE = 400, PWM OUTPUT = 1023
}; |
Fix to Question2 and Question3:
Code: | if(Result_X == Store_X[i][0] ) //Comparing Result_X
{
Set_PWM1_Duty( Store_X[i][1]); /
delay_ms(10);
}
else
{
Set_PWM1_Duty(0); //Turn Off the Fan
delay_ms(10);
} |
|
|
|
RossJ
Joined: 25 Aug 2004 Posts: 66
|
|
Posted: Thu Jun 14, 2007 8:40 pm |
|
|
Hi Srig,
The reason to use sizeof() is to let the compiler determine how big the array is rather than hard coding it. That way you can't get it wrong. If in the future you add one extra pair of values to the table, the loop will still work correctly. The 'divide by 4' bit is because sizeof() return the number of bytes, but the loop iterates through the rows (4 bytes each).
I think you have a logic problem with your loop and table lookup. My guess is that you want to read the sensor, and use that value to run the fan at some appropriate speed in response. The table defines the relationship between temperature and speed.
The problem is that the ADC can return values in between the ones in your table. Since you are using '==' and not '<' (or similar) in the if statement, you will end up stopping the fan just becuase there is not exact match in the table (which will be most of the time, since you only have 11 entries). I suggest you do something like this...
Code: |
for (i = 0; i < sizeof(Store_X) / 4; ++i)
{
if (Result_X <= Store_X[i][0]) //Comparing Result_X
{
Set_PWM1_Duty(Store_X[i][1]); /
delay_ms(10);
}
}
|
This will work as long as Store_X[i][0] is in increasing order in the table, and you have table rows to cover the boundary conditions. This means you need to cover all possible ADC values. At the very least this means one extra row at the end of the table.
As for the ADC reference voltage... You wont damage the PIC if the input voltage exceeds the reference, so long as you don't exceed VCC (see datasheet for exact voltages). However, the reference determines the voltage which will be reported by the ADC as the highest value (which depends on the resolution you use, i.e. 1023 (10 bits) or 4095 (12 bits).
What voltage range do you expect to get from the sensor?
/Ross. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|