• AVR Freaks

Newbie: controlling duty cycle of PWM set up with MCC

Page: 12345.. > >> Showing page 1 of 14
Author
SGK
Senior Member
  • Total Posts : 158
  • Reward points : 0
  • Joined: 2018/05/14 13:55:08
  • Location: 0
  • Status: offline
2018/05/18 07:06:30 (permalink)
0

Newbie: controlling duty cycle of PWM set up with MCC

Hi
 
First of all, sorry for the basic question but I am a newbie taking first steps in PIC programming and C coding.  My project is to use a PIC16F1829 to control an external timer that has two relays (yes I know the PIC could, eventually, replace this timer), monitor an IR switch to determine if things are ready for operation, and monitor 4 NTCs for temperature and control 2 fans with 25kHz PWM (2 NTC per fan). The external timer's relays control power to an inductor board and a linear pull solenoid on a trap door while allowing easy time setting by a user. The IR switch looks to see if there is a case in the inductor coil ready for heating thereby automating start. PIC monitoring of the NTCs will be used to control fan PWM as things heat up out back and also halt operation if things get too hot (except the item in the inductor coil of course). 
 
I have used MCC to setup the PIC. Luckily for me this is available as I still don't understand all of the settings and register stuff.  So far I have coded the operation of the external timer, monitoring of the IR switch and checking the NTC temperatures. Now I am looking at the PWM side of things.
 
Clock is set to INTOSC 8MHz. (PLL is enabled - not sure if this is needed.) Both CCP3 and CCP4 use Timer2. I have this postscaler set to 1:1 and prescaler 1:16, time period 40uS. Each CCP is in PWM mode, 50% duty cycle. PWM resolution is given as 4 bits. 50% duty cycle has a CCPR value of 9 and that CCPR values can range from 0-19 (0% to 100% duty cycle).
 
MCC has coded the following function (?) which resides in pwm3.c (and its sibling in pwm4.c):
 
void PWM4_LoadDutyValue(uint16_t dutyValue)
{
// Writing to 8 MSBs of pwm duty cycle in CCPRL register
CCPR4L = ((dutyValue & 0x03FC)>>2);

// Writing to 2 LSBs of pwm duty cycle in CCPCON register
CCP4CON = ((uint8_t)(CCP4CON & 0xCF) | ((dutyValue & 0x0003)<<4));
}
 
Q1: Can I change PWM4 to something more meaningful e.g. FAN2? I assume I would have to change it throughout pwm4.h and pwm4.c.
 
Q2:  is this expecting a number between 0 and 19 only? I think this is correct but I am unsure. Example:
 
PWM4_LoadDutyValue(12);
 
Q3:  what controls the number of bits for the PWM resolution and, if I wanted to, can I change it? I've seen tutorials with higher PWM resolution.
Q4:  even leaving it at 10 steps between 50% duty and 100% duty that's a lot of If statements to check temperatures and determine the appropriate duty cycle bucket.  And all that twice. Is there a more efficient way to code things?
 
Thanks in advance for the help and apologies once again if these are very basic questions.
 
Steve
#1

279 Replies Related Threads

    katela
    Super Member
    • Total Posts : 1635
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 08:40:06 (permalink)
    +1 (1)
    SGK
    Hi 
    Q2:  is this expecting a number between 0 and 19 only? I think this is correct but I am unsure. Example: 
    PWM4_LoadDutyValue(12);

    Yes. according to your configuration, you can change the duty cycle for 0% to 100% using PWM4_LoadDutyValue().
    SGK
    Q3:  what controls the number of bits for the PWM resolution and, if I wanted to, can I change it? I've seen tutorials with higher PWM resolution.

    Your PIC has a maximum of  10-bit resolution.
    In the datasheet on section 24.3.6 PWM RESOLUTION, The resolution is a function of the PRx register value as shown by Equation 24-4. 
    TABLE 24-5, TABLE 24-6 and TABLE 24-7 shows EXAMPLES OF PWM FREQUENCIES AND RESOLUTIONS.
    In brief with MCC, by changing your Clock frequency or Timer Period will change the PWM resolution. 
    You can learn more from: http://microchipdeveloper.com/8bit:10bitpwm
     
    post edited by katela - 2018/05/18 08:42:41

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #2
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 08:54:57 (permalink)
    +1 (1)
    Thanks.  (And thanks for your videos.) 
     
    Hopefully someone will chime in on Q1 and Q4. Else I will persevere the log way for Q4. Right now I can't get fmax(a,b)  [where a and b are of type double] to work in order to get the highest of the two NTC temps per fan. Ugh.  
    #3
    jack@kksound
    code tags!
    • Total Posts : 3224
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 09:48:03 (permalink)
    +2 (2)
    Q1: Can I change PWM4 to something more meaningful e.g. FAN2? I assume I would have to change it throughout pwm4.h and pwm4.c.

    Refactor/Rename option in mplabx.
    You should be careful changing MCC generated code. If you make changes to the code/headers then go back to MCC and make changes and generate new code you will need to reconcile the changes you made directly to the old code with the new code produced by MCC. You will get a side-by-side comparison of the old vs new to faciltate this but it can be a big task if extensive changes are made (at least in my experience).
     
    #4
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 10:48:26 (permalink)
    0
    Ok sounds like I should not bother for now.  Thanks. 
     
    What is wrong with this code:
     
    #include <math.h>
     
    double High_Temp_Fan1=0;
    High_Temp_Fan1 = fmax(Temp_NTC1, Temp_NTC2);
     
    Each of Temp_NTC1 and Temp_NTC2 are of type double and are the returned values from my function which takes the ADC values and converts them into temps in degrees Celsius. 
     
    The compiler has a problem with max and yet I thought this math function was included in math.h. http://en.cppreference.com/w/c/numeric/math/fmax 
     
    (I'm trying to at least shorten slightly my nested if for setting duty cycle.)
    #5
    jack@kksound
    code tags!
    • Total Posts : 3224
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 11:56:10 (permalink)
    +1 (1)
    fmax() function is not included in the math.h header file of XC8 so of course the compiler will raise an error.
    You are looking at a c++ reference, you will find many differences between c++ and c. If you check the XC8 User Guide you will not find fmax() listed in Appendix A: Library Functions
    #6
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:15:00 (permalink)
    +1 (1)
    OK.  Doesn't look like there is an equivalent so I will use an if statement to compute the maximum. Thanks 
     
    It would be helpful if Help worked. Help->Help Contents produces a blank window on my Mac!
     
    Onward to trying to add EUSART so I can connect via a USB to serial adapter and check temps and duty cycles.  Reading a couple of tutorials now!
    #7
    jack@kksound
    code tags!
    • Total Posts : 3224
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:17:26 (permalink)
    0
    It would be helpful if Help worked. Help->Help Contents produces a blank window on my Mac!

    Works OK on Win 10, maybe an installation issue?
    #8
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:34:45 (permalink)
    0
    No idea but I only installed the software for the first time 3 days ago.  If someone can confirm it is working on a Mac I will dig deeper.  For now I will plod along. 
     
    I have added EUSART [PIC10/ etc]. I understand I could just code such that the PIC writes the temps and duty cycles every so often.  But it would be better to be able to query them (i.e. on demand) and have the ability to change key variables via the serial communication. I assume the latter, at least, requires me to enable the Global and Peripheral Interrupts.  I am following this tutorial:  http://microchipdeveloper.com/mcu1101:project-12 (albeit without the development board etc). 
    #9
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:37:28 (permalink)
    0
    But I get errors as soon as I remove the //
    #10
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:41:21 (permalink)
    0
    Fixed by enabling TXI and TCI in Interrupt Module
     
    #11
    katela
    Super Member
    • Total Posts : 1635
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:45:12 (permalink)
    0
    SGK
    But I get errors as soon as I remove the //


    Which "//", always post the code that gives you errors and also the error messages. 
     "//" are just comments, maybe you wanted to enable comments which are not C syntax or were not supposed to be part of the code.

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #12
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:49:32 (permalink)
    0
    Sorry. This code in main.c.  By default all the Interrupt lines are commented out.  When I initially removed the two sets of // I got errors.  I needed to enable TXI and RXI in the Interrupt Module.  Now I just need to figure out the serial code. 
     
    MAIN APPLICATION
    */
    void main(void)
    {
    // initialize the device
    SYSTEM_Initialize();
    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:
    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();
    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();
    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();
    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();
    #13
    katela
    Super Member
    • Total Posts : 1635
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:55:13 (permalink)
    0
    Yes you must configure (enable) the interrupts first before commenting them out.

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #14
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 12:57:09 (permalink)
    0
    Yup.  The Microchip Developer Help Tutorial skipped that bit.
    #15
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 13:40:50 (permalink)
    +1 (1)
    BTW I just watched another of your videos https://www.youtube.com/watch?v=jLRTTHI9m94
     
    I am wondering why you created the function send_string as opposed to simply using printf
    #16
    SGK
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2018/05/14 13:55:08
    • Location: 0
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 14:09:31 (permalink)
    0
    I have one more question before I take a break and return later with an attempt at coding the serial stuff.
    [Basically I want to be able to request computer display of temps and duty cycles without interrupting operation of the device AND be able to interrupt operation to program certain parameters (e.g. the levels at which duty cycles change or the temperature at which an 'over-temp' condition occurs and operation is halted).]
     
    When I look at my main.c code as it stands now I see I have two while loops. It seems redundant to have two. Can one be deleted?
     
     
     
    #include "mcc_generated_files/mcc.h"
    #include <math.h>
    /*
    MAIN APPLICATION
    */
    void main(void)
    {
    // initialize the device
    SYSTEM_Initialize();
    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:
    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();
    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();
    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();
    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();
     
    while (1)
    {

    //SET UP TIMER AND OPTICAL SWITCH PARAMETERS

    IRswitch_SetDigitalInput();
    TimerStart_SetDigitalOutput();
    OvrTmpLED_SetDigitalOutput();
    TimerStart_SetLow();
    OvrTmpLED_SetLow();                                             //Set Over Temp LED off
    char Switch_Cleared = 'N';
    #define NO_CASE (IRswitch_GetValue()==HIGH)      //IR beam not blocked
    #define CASE (IRswitch_GetValue()==LOW)             //IR beam blocked
    double Temp_NTC1=0;                                            //Storage of checked temperatures in degrees Celsius
    double Temp_NTC2=0;
    double Temp_NTC3=0;
    double Temp_NTC4=0;
    double over_temp = 70;                                         //Define temperature for shutdown protection
    double readNTC1();
    double readNTC2();
    double readNTC3();
    double readNTC4();
    double Temp_Limit1=30;                                       //Fan control temperature buckets in degrees Celsius
    double Temp_Limit2=33;
    double Temp_Limit3=36;
    double Temp_Limit4=39;
    double Temp_Limit5=42;
    double Temp_Limit6=45;
    double Temp_Limit7=48;
    double Temp_Limit8=51;
    double Temp_Limit9=54;
    double Temp_Limit10=57;


    while (1)
    {

    Temp_NTC1 = readNTC1();           //Read temperatures
    Temp_NTC2 = readNTC2();
    Temp_NTC3 = readNTC3();
    Temp_NTC4 = readNTC4();

    // Set FAN duty cycles

    double High_Temp_Fan1=0;
    if (Temp_NTC1>=Temp_NTC2)
    {
    High_Temp_Fan1=Temp_NTC1;
    }
    else
    High_Temp_Fan1=Temp_NTC2;

    if (High_Temp_Fan1>=Temp_Limit1 && High_Temp_Fan1<Temp_Limit2) {PWM4_LoadDutyValue(10);}
    if (High_Temp_Fan1>=Temp_Limit2 && High_Temp_Fan1<Temp_Limit3) {PWM4_LoadDutyValue(11);}
    if (High_Temp_Fan1>=Temp_Limit3 && High_Temp_Fan1<Temp_Limit4) {PWM4_LoadDutyValue(12);}
    if (High_Temp_Fan1>=Temp_Limit4 && High_Temp_Fan1<Temp_Limit5) {PWM4_LoadDutyValue(13);}
    if (High_Temp_Fan1>=Temp_Limit5 && High_Temp_Fan1<Temp_Limit6) {PWM4_LoadDutyValue(14);}
    if (High_Temp_Fan1>=Temp_Limit6 && High_Temp_Fan1<Temp_Limit7) {PWM4_LoadDutyValue(15);}
    if (High_Temp_Fan1>=Temp_Limit7 && High_Temp_Fan1<Temp_Limit8) {PWM4_LoadDutyValue(16);}
    if (High_Temp_Fan1>=Temp_Limit8 && High_Temp_Fan1<Temp_Limit9) {PWM4_LoadDutyValue(17);}
    if (High_Temp_Fan1>=Temp_Limit9 && High_Temp_Fan1<Temp_Limit10) {PWM4_LoadDutyValue(18);}
    if (High_Temp_Fan1>=Temp_Limit10) {PWM4_LoadDutyValue(19);}

    double High_Temp_Fan2=0;
    if (Temp_NTC3>=Temp_NTC4)
    {
    High_Temp_Fan2=Temp_NTC3;
    }
    else
    High_Temp_Fan2=Temp_NTC4;

    if (High_Temp_Fan2>=Temp_Limit1 && High_Temp_Fan2<Temp_Limit2) {PWM3_LoadDutyValue(10);}
    if (High_Temp_Fan2>=Temp_Limit2 && High_Temp_Fan2<Temp_Limit3) {PWM3_LoadDutyValue(11);}
    if (High_Temp_Fan2>=Temp_Limit3 && High_Temp_Fan2<Temp_Limit4) {PWM3_LoadDutyValue(12);}
    if (High_Temp_Fan2>=Temp_Limit4 && High_Temp_Fan2<Temp_Limit5) {PWM3_LoadDutyValue(13);}
    if (High_Temp_Fan2>=Temp_Limit5 && High_Temp_Fan2<Temp_Limit6) {PWM3_LoadDutyValue(14);}
    if (High_Temp_Fan2>=Temp_Limit6 && High_Temp_Fan2<Temp_Limit7) {PWM3_LoadDutyValue(15);}
    if (High_Temp_Fan2>=Temp_Limit7 && High_Temp_Fan2<Temp_Limit8) {PWM3_LoadDutyValue(16);}
    if (High_Temp_Fan2>=Temp_Limit8 && High_Temp_Fan2<Temp_Limit9) {PWM3_LoadDutyValue(17);}
    if (High_Temp_Fan2>=Temp_Limit9 && High_Temp_Fan2<Temp_Limit10) {PWM3_LoadDutyValue(18);}
    if (High_Temp_Fan2>=Temp_Limit10) {PWM3_LoadDutyValue(19);}

    if (Temp_NTC1 < over_temp &&             // Check no over-temp condition
    Temp_NTC2 < over_temp &&
    Temp_NTC3 < over_temp &&
    Temp_NTC4 < over_temp)

    //Normal operation of optical switch and timer management
    {
    OvrTmpLED_SetLow();                 //Make sure Over-Temp LED is off
    if (CASE && (Switch_Cleared=='Y'))
    {
    for (int countDelay=0; countDelay <100; countDelay ++)__delay_ms(5);         //Delay 0.5s for case to settle
    if (CASE)
    {
    TimerStart_SetHigh();    //Emulate push to make switch
    for (int countDelay=0; countDelay <20; countDelay ++)__delay_ms(5);
    TimerStart_SetLow();
    }
    }
    else
    {
    if (NO_CASE) Switch_Cleared='Y';
    }
    }

    else /              /Over-temp situation. Blink LED and halt operation until temps clear shutdown threshold

    {
    OvrTmpLED_Toggle();
    for (int countdelay=0; countdelay<20; countdelay++)__delay_ms(10);

    }

    }
    }
    }

    //FUNCTIONS Calculate temp at each NTC in degrees Celsius
    double readNTC1()
    {
    const double NTC_Balance_Resistor = 10000; //Balance resistor in NTC voltage divider
    const double Max_ADC = 1023; //10 bit DAC
    const double NTC_Beta = 3445; //From datasheet
    const double Room_TempK = 298.15;
    const double Res_Room_Temp = 10000; //10K NTC
    double NTC1 = 0;
    double ADC_reading_NTC1 = 0;
    ADC_reading_NTC1 = ADC_GetConversion(NTC1);
    double rNTC1 = 0;
    rNTC1 = NTC_Balance_Resistor * ((Max_ADC / ADC_reading_NTC1)-1);
    NTC1 = ((NTC_Beta * Room_TempK) /
    (NTC_Beta + (Room_TempK * log(rNTC1 / Res_Room_Temp)))) - 273.15;
    return NTC1;
    }
    double readNTC2()
    {
    const double NTC_Balance_Resistor = 10000; //Balance resistor in NTC voltage divider
    const double Max_ADC = 1023; //10 bit DAC
    const double NTC_Beta = 3445; //From datasheet
    const double Room_TempK = 298.15;
    const double Res_Room_Temp = 10000; //10K NTC
    double NTC2 = 0;
    double ADC_reading_NTC2 = 0;
    ADC_reading_NTC2 = ADC_GetConversion(NTC2);
    double rNTC2 = 0;
    rNTC2 = NTC_Balance_Resistor * ((Max_ADC / ADC_reading_NTC2)-1);
    NTC2 = ((NTC_Beta * Room_TempK) /
    (NTC_Beta + (Room_TempK * log(rNTC2 / Res_Room_Temp)))) - 273.15;
    return NTC2;
    }

    double readNTC3()
    {
    const double NTC_Balance_Resistor = 10000; //Balance resistor in NTC voltage divider
    const double Max_ADC = 1023; //10 bit DAC
    const double NTC_Beta = 3445; //From datasheet
    const double Room_TempK = 298.15;
    const double Res_Room_Temp = 10000; //10K NTC
    double NTC3 = 0;
    double ADC_reading_NTC3 = 0;
    ADC_reading_NTC3 = ADC_GetConversion(NTC3);
    double rNTC3 = 0;
    rNTC3 = NTC_Balance_Resistor * ((Max_ADC / ADC_reading_NTC3)-1);
    NTC3 = ((NTC_Beta * Room_TempK) /
    (NTC_Beta + (Room_TempK * log(rNTC3 / Res_Room_Temp)))) - 273.15;
    return NTC3;
    }
     
    double readNTC4()
    {
    const double NTC_Balance_Resistor = 10000; //Balance resistor in NTC voltage divider
    const double Max_ADC = 1023; //10 bit DAC
    const double NTC_Beta = 3445; //From datasheet
    const double Room_TempK = 298.15;
    const double Res_Room_Temp = 10000; //10K NTC
    double NTC4 = 0;
    double ADC_reading_NTC4 = 0;
    ADC_reading_NTC4 = ADC_GetConversion(NTC4);
    double rNTC4 = 0;
    rNTC4 = NTC_Balance_Resistor * ((Max_ADC / ADC_reading_NTC4)-1);
    NTC4 = ((NTC_Beta * Room_TempK) /
    (NTC_Beta + (Room_TempK * log(rNTC4 / Res_Room_Temp)))) - 273.15;
    return NTC4;
    }
    /**
    End of File
    */
     
     
    #17
    katela
    Super Member
    • Total Posts : 1635
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 15:32:37 (permalink)
    0
    SGK
    BTW I just watched another of your videos https://www.youtube.com/watch?v=jLRTTHI9m94
     
    I am wondering why you created the function send_string as opposed to simply using printf

    You can also use printf

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #18
    katela
    Super Member
    • Total Posts : 1635
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 15:55:43 (permalink)
    0
    SGK
     
    When I look at my main.c code as it stands now I see I have two while loops. It seems redundant to have two. Can one be deleted?
     

    You can't have two while (1) loops like that.
    You can have more than one while (1) loops only if you're gonna have some "break" conditions to break out of the loop and continue with your main code, in scenarios where you are expecting input data from users like reading a keypad to enter some settings for example, you might use a while (1)  loop to basically stay there until maybe the Enter key is pressed for example. that will be the "break condition":

    if(kp==ENTER)break; //Exit from the loop when kp == Enter.

    But the other way is to put a condition inside the while () loop. for example in the code below if (i == 5) break; //Exit from the loop when i=5. The output will only print Loop iteration 1 up to 4.

    int i = 0; 
    while (i < 10)

    {

        i++;

     
        if (i == 5) break; //Exit from the loop when i=5.

                            //Iteration 6-9 will not be executed.

        printf("Loop iteration %d\n", i);

    }


    A code inside a while (1) loop will loop forever and will never continue with the rest of your code unless you have a "break" condition in your loop because '1' will always be true.
    Setup or calculation codes can be in separate functions and only called inside your while (1) loop depending on the logic of your code.
    post edited by katela - 2018/05/18 15:59:35

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #19
    PStechPaul
    Super Member
    • Total Posts : 2558
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: offline
    Re: Newbie: controlling duty cycle of PWM set up with MCC 2018/05/18 16:02:40 (permalink)
    +2 (2)
    It's difficult to follow your code as posted. Please use [ code] and [ /code] tags (without the spaces), so it looks like this:
    double readNTC1()
    {
    const double NTC_Balance_Resistor = 10000; //Balance resistor in NTC voltage divider
    const double Max_ADC = 1023; //10 bit DAC
    const double NTC_Beta = 3445; //From datasheet
    const double Room_TempK = 298.15;
    const double Res_Room_Temp = 10000; //10K NTC
    double NTC1 = 0;
    double ADC_reading_NTC1 = 0;
    ADC_reading_NTC1 = ADC_GetConversion(NTC1);
    double rNTC1 = 0;
    rNTC1 = NTC_Balance_Resistor * ((Max_ADC / ADC_reading_NTC1)-1);
    NTC1 = ((NTC_Beta * Room_TempK) /
    (NTC_Beta + (Room_TempK * log(rNTC1 / Res_Room_Temp)))) - 273.15;
    return NTC1;
    }

    Other pointers:
     
    (1) Unless you have a strong valid reason, you should not use floating point (double). It greatly slows the processing and uses a lot of memory. Integer and long should be sufficient, and you can convert to float for visual display when needed. If you need the precision you can do something like "const Room_Temp_x100 = 27315"
     
    (2) As a general rule, code that is repeated several places, as that within your functions, should be combined in a single function with an argument that changes how it works. Something like:
    float Read_NTC(int num) {
     
    int adcval = ADC_GetConversion(num);
    float rNTC = NTC_Balance_Resistor * ((Max_ADC / (float)adcval)-1); // Cast to float
    NTC = ((NTC_Beta * Room_TempK) / (NTC_Beta + (Room_TempK * log(rNTC / Res_Room_Temp)))) - REFTEMP;
    return NTC; }

     
    The constants would be best defined before the code in one place, like this:
    #define REFTEMP 273.15
    #define NTC_Balance_Resistor 10000
    #define NTC_Beta = 3445
    #define Max_ADC 1023
    #define Room_TempK 298.15

     
    (3) It might be better to use a look-up table to convert directly from ADC reading to temperature
     
    (4) Your temperature limits would be better expressed as an array
    int Temp_Limit[] = {30,33,36,39,42,45,48,51,54,57}; //Fan control temperature buckets in degrees Celsius

     
    (5) You might use a switch/case structure:
    int Temp_Range = ((int)ReadNTC(n)-30)/3; // Temperature ranges reduced to {0,1,2,3,4,5,6,7,8,9}
    switch (Temp_Range) {
      case 0: PWM3_LoadDutyValue(10); break;
      case 1: PWM3_LoadDutyValue(11); break;
    ...
      default: Handle_Overtemp(n); }

     
    You will need to make some changes to handle the appropriate PWMs for the fans. There are other ways to simplify the code as well.

     
    #20
    Page: 12345.. > >> Showing page 1 of 14
    Jump to:
    © 2020 APG vNext Commercial Version 4.5