• AVR Freaks

Newbie: controlling duty cycle of PWM set up with MCC

Page: << < ..678910.. > >> Showing page 7 of 14
Author
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/30 09:59:10 (permalink)
0
I'm still trying to figure out debugging, either via the Pickit 3 or Simulator. Many tutorials seem out of date versus what is displayed before me. I can't get the scrolling green arrow showing me where in the code the program is (or an ability to control the speed). However, it seems to be stuck here
 

//Send String
void Send_String(const char *x)
{
while (*x)
{
EUSART_Write(*x++);
}
}

 
I took that function from one of katela's videos.
 
Here is the MCC-generated EUSART_Write function:
 

void EUSART_Write(uint8_t txData)
{
while(0 == eusartTxBufferRemaining)
{
}
if(0 == PIE1bits.TXIE)
{
TXREG = txData;
}
else
{
PIE1bits.TXIE = 0;
eusartTxBuffer[eusartTxHead++] = txData;
if(sizeof(eusartTxBuffer) <= eusartTxHead)
{
eusartTxHead = 0;
}
eusartTxBufferRemaining--;
}
PIE1bits.TXIE = 1;
}

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/30 10:00:52 (permalink)
0
I split the long strings separated by \n into individual Send_String commands but it made no difference. 
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/30 14:30:05 (permalink)
0
PStechPaul
 
I strongly suggest that you use the debug capability of the PICkit3 to trace execution.

 
When I run the debugger I do not get a green arrow showing me which part of the code is being run.  Also, I can't trace variables, only constants and functions.  (Even with  NOP() added before the first Send_String command.) Frustrating. 
 
 
PStechPaulMaybe some problems here:
float rNTC = NTC_Balance_Resistor * ((Max_ADC / ADC_value)-1);
float Temp = ((NTC_Beta * Room_TempK) / (NTC_Beta + (Room_TempK * log(rNTC / Res_Room_Temp)))) - 273.15;

 
This is what I have for temperature:
 
TdegC = T0DegK * B / ( T0DegK * LN( ( ADC * Rser ) / ( R0 * ( 2 ^ Bits ) - ADC ) ) ) + B ) - 273
 



I have edited my code above to reflect removal of some of the redundant parentheses and making rNTC1 generic by removing the 1. (There are still some redundant parentheses.) I'm following this here (without the averaging).  Scroll down to the comments in the code box. 
 
https://www.allaboutcircuits.com/projects/measuring-temperature-with-an-ntc-thermistor/
 
 
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/30 14:45:50 (permalink)
0
You don't really need to use those functions for the EUSART. And it can get stuck here:
while(0 == eusartTxBufferRemaining)
{
}

I think you need to master some of the basics before trying to code your entire project. The EUSART buffers are only used so that you can write multiple characters to the serial port very quickly and then do other things while the buffer is being emptied. But the function as written will block further processing if the buffer is full. You will also need to set up interrupts for this to work in the background. Until you fully understand these dynamics, you would be better off using a simple function for EUSART_write().
 
Effective debugging usually involves running the code up to a breakpoint, where execution will stop and you can view the contents of various registers and variables. If you stop simulation and it appears hung up at a certain point in the code, you can determine why it is stuck there. If eusartTxBufferRemaining is zero, there must be a background process (ISR) that does something to make it non-zero to allow further execution and return from the function.
 
You are probably anxious to get on with your project, but I think you need to take the time, perhaps a few days, to go through some basic tutorials and fully understand the concepts.
 
Using MCC may have seemed like a quick and easy way to get up to speed, but it is really an imperfect and difficult tool that can greatly complicate your code and cause confusion and despair.

 
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/30 15:16:04 (permalink)
0
PStechPaul
You don't really need to use those functions for the EUSART. And it can get stuck here:
while(0 == eusartTxBufferRemaining)
{
}

 
 
I think you need to master some of the basics before trying to code your entire project. The EUSART buffers are only used so that you can write multiple characters to the serial port very quickly and then do other things while the buffer is being emptied. But the function as written will block further processing if the buffer is full. You will also need to set up interrupts for this to work in the background. Until you fully understand these dynamics, you would be better off using a simple function for EUSART_write().
.
.
.
Using MCC may have seemed like a quick and easy way to get up to speed, but it is really an imperfect and difficult tool that can greatly complicate your code and cause confusion and despair.

 
I'm confused. EUSART_Write() is a function created by MCC.  I am only attempting to use the 'simple function' EUSART_Write(). I understand that this writes one character only and so to write a string we need a While() loop:
 

//Send String
void Send_String(const char *x)
{
while (*x)
{
EUSART_Write(*x++);
}
}

 
BTW I note the * superscripts here but not in MPLAB. 
 
I've not poked into the construction of the MCC generated function.  If you are saying that MCC is fundamentally flawed then I am up the proverbial creek without a paddle.
 
PStechPaul
Effective debugging usually involves running the code up to a breakpoint, where execution will stop and you can view the contents of various registers and variables.

 
This I understand.  I set up a break point immediately before Send_Welcome() - right towards the start of the main While () loop. As I understand it from all the tutorials I have watched, unfortunately none of which are from MPLAB X IDE, I can pause at a break point and view the value of any variable I have used in my program. Yet while I can see constants and functions in the drop-down list, I do not see any general variables used in the code such as Fan1_DC, High_Temp_Fan1, Temp_NTC1 etc etc. Furthermore, as an example, DC50_Limit, an eprom stored constant given a value of 30, is shown as having a value of 0.  None of this is making sense. It is severely challenging to have available only tutorials which are clearly using older versions of the product and which show access to useful information which I can't replicate.
 
PStechPaulIf you stop simulation and it appears hung up at a certain point in the code, you can determine why it is stuck there. If eusartTxBufferRemaining is zero, there must be a background process (ISR) that does something to make it non-zero to allow further execution and return from the function.

 
It would be helpful to know where in the code things have stopped.  Several tutorials - again using prior versions of MPLAB IDE - show a green arrow moving through the code as things are processed and even the ability to control the speed at which the code is processed.  I don't see any of this. I keep searching for something more up-to-date. This debugger is not at all intuitive. 
 
PStechPaulYou are probably anxious to get on with your project, but I think you need to take the time, perhaps a few days, to go through some basic tutorials and fully understand the concepts.

 
Agreed on both. The key issue at the moment is I have yet to get the debugger to be of any assistance. I will persevere.
 
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/30 16:41:17 (permalink)
0
I finally managed to get a green arrow in debugging by setting the preferences for debug startup to halt at main. I can then step one line at a time. It goes into SYSTEM_Initialize() -> PIN_MANAGER _INITIALIZE() -> pin_manager.c ->through setting the LATx registers and then crashes with the following error when it gets to the TRISx registers
 
The target device is not ready for debugging. Please check your configuration bit settings and program the device before proceeding. The most common causes for this failure are oscillator and/or PGC/PGD settings.
Failed getting PC
 
Lovely. 
 
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/30 17:29:16 (permalink)
0
Perhaps you have some circuitry connected to the programming/debugging pins, or something that is loading or creating noise in the Vdd power. At this point, it may be advantageous to use the software simulator, although it does not seem to work very well for the serial port. You can simulate that using register injection as I may have shown earlier. If not, here is the basic concept:
char    RXDsim[] = {'B','1','2','3','4','\r','S',' ','7','6','5','\r', 'X','\r'};
int     RXDptr = -1;

char    EUSART_Read(void) {
//    while(!RCIF);
//    return  RCREG;
    if(RXDptr < sizeof(RXDsim)-1)
        RXDptr++;
    else
        RXDptr = 0;
    return RXDsim[RXDptr];
}

The commented code can be used in place of the MCC generated function. You can do something similar for EUSART_write();

char* EUSARTbuf[20];
int EUSARTptr = -1;
 
void EUSART_Write (char TxData) {
if(EUSARTptr<18)
  EUSARTptr++;
else
  EUSARTptr=0;
EUSARTbuf[EUSARTptr] = TxData;
}

It would be better to get a simple serial port application working first. You can just write to TXREG after waiting for TXIF to be set, indicating TXREG is clear for a new character to be accepted for transmission.
 
post edited by PStechPaul - 2018/05/31 14:22:11

 
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/30 18:25:32 (permalink)
0
Nothing connected to PIC and only a universal seat connected to the Pickit. It bombs at exactly the same point in pin_manager.c every time - right at TRISB = 0xD0;  
 
Port B4 (pin 13) is an ADC input for an NTC.   Port B5 (pin 12) is a GPIO for the Over Temp LED. Port B6 (pin 11) is unused. Port B7 (pin 10) is Tx. 
 

#include <xc.h>
#include "pin_manager.h"
#include "stdbool.h"
 
 
void PIN_MANAGER_Initialize(void)
{
/**
LATx registers
*/
LATA = 0x00;
LATB = 0x00;
LATC = 0x00;
/**
TRISx registers
*/
TRISA = 0x2B;
TRISB = 0xD0;
TRISC = 0xBF;
/**
ANSELx registers
*/
ANSELC = 0xCF;
ANSELB = 0x10;
ANSELA = 0x01;
/**
WPUx registers
*/
WPUB = 0x00;
WPUA = 0x00;
WPUC = 0x00;
OPTION_REGbits.nWPUEN = 1;
/**
ODx registers
*/
/**
APFCONx registers
*/
APFCON0 = 0x80;
APFCON1 = 0x00;
 



}

void PIN_MANAGER_IOC(void)
{
}
/**
End of File
*/

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/30 18:44:59 (permalink)
0
A thought. Pins 18 and 19 have not been configured for PGC PGD in any way. They're unused (blue) in package view. Is this a problem?
 
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/30 19:46:44 (permalink)
0
If the debugger stops at TRISB=0xD0, the problem could occur on the previous line where TRISA=0x2B. That is how setpoints work. I don't see anything wrong with that code, but perhaps it has something to do with RA3 which may be configured as MCLR or GP input, as well as Vpp for programming. The ICSPCLK(RA1) and ICSPDAT(RA0) pins are used for debugging, and it looks like they are set as digital input, which should be OK. You set ANSELA=0x01, so RA0 is analog, and that might be a problem.

 
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/31 06:19:27 (permalink)
0
RA3 (pin 4) is set to MCLR. I understood this is necessary for on-board debugging. I had initially set it to digital input. I changed RA0 to digital but it made no difference.   I will switch to the Simulator and see if I get further.
 
(I was going to post a zip of the project but the file is too big.)
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/31 08:17:12 (permalink)
0

  The software license has expired.   What's up with this forum?

 
Ok the Simulator allowed more progress. I've identified where the program hangs. It is right at the first Send_String command and, as you noted above, the problem is with the MCC generated function void EUSART_Write(uint8_t txData) in eusart.c. More specifically the first while() statement:
 

void EUSART_Write(uint8_t txData)
{
while(0 == eusartTxBufferRemaining)
{
}

 
According to the Sim eusartTxBufferRemaining has a value of NUL; 0x0 or 0 in decimal format. Yet the program can't move on. 
 
A few other things I noticed:
 
Despite having 
eeprom int DC50_Limit = 30; //Temperature limit for 50% duty cycle operation
 
DC50_Limit is shown as having a value of 0! The following work ok:
 
eeprom int NTC_Beta = 3435; //NTC beta from data sheet
eeprom int Over_Temp = 70;
 
I don't understand why DC50_Limit doesn't. 
 
For the sim the ADC values are coming back as 0 because I am not providing any stimuli (not worried about that for now) which means there's a divide by 0 in the formula for rNTC but I think this simply leaves the NTCx_Temp at their initialised states of 25. I noticed Duty_Cycle is coming back as 55 rather than 50 and I need to check my formula there but I need to get DC50_Limit sorted first. 
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/31 08:46:20 (permalink)
0
Regarding DC50_Limit, if I reverse the order of setting the variables so that DC50_Limit comes before Over_Temp
 

eeprom int NTC_Beta = 3435; //NTC beta from data sheet
eeprom int DC50_Limit = 30; //Temperature limit for 50% duty cycle operation
eeprom int Over_Temp = 70; //Temperature limit for shutdown

 
DC50_Limit is recorded with the correct value but Over_Temp is set to 0. Huh? Maybe I need a dummy 4th as a workaround...
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/31 09:55:38 (permalink)
0
When one uses MCC to set up EUSART printf is set up to go to serial via the EUSART functions such as EUSART_Write. I changed my welcome string to:
 

//Send Welcome String
void Send_Welcome(void)
{
printf("GinaErick Annealer software by SGK ver 1.0 May 20, 2018. Copyright (c) protected. Non-commercial use only.\n");
printf("Type T to display NTC temperatures and fan duty cycles.\nType P to enter program mode.\n");
}

 
When it gets stuck - same place - eusartTxBuffer has the value "inaErick" and sometimes it is all NUL; 0x0. 
 
I'm struggling to believe that MCC's implementation of EUSART is really that flawed.
 

uint8_t EUSART_Read(void)
{
uint8_t readValue = 0;

while(0 == eusartRxCount)
{
}
readValue = eusartRxBuffer[eusartRxTail++];
if(sizeof(eusartRxBuffer) <= eusartRxTail)
{
eusartRxTail = 0;
}
PIE1bits.RCIE = 0;
eusartRxCount--;
PIE1bits.RCIE = 1;
return readValue;
}
void EUSART_Write(uint8_t txData)
{
while(0 == eusartTxBufferRemaining)
{
}
if(0 == PIE1bits.TXIE)
{
TXREG = txData;
}
else
{
PIE1bits.TXIE = 0;
eusartTxBuffer[eusartTxHead++] = txData;
if(sizeof(eusartTxBuffer) <= eusartTxHead)
{
eusartTxHead = 0;
}
eusartTxBufferRemaining--;
}
PIE1bits.TXIE = 1;
}

 
 
 
 
 
 
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/31 12:56:30 (permalink)
0
Maybe I need a dummy 4th as a workaround...

 
A dummy fixes this issue so long as the dummy is not set to zero:
 

eeprom int NTC_Beta = 3435; //NTC beta from data sheet
eeprom int DC50_Limit = 30; //Temperature limit for 50% duty cycle operation
eeprom int Over_Temp = 70; //Temperature limit for shutdown
eeprom int dummy = 10;

 
Tres weird.
 
Thanks to the simulator debugger I've identified and fixed a couple of errors in my duty cycle setting code which is good. 
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/31 13:23:38 (permalink)
0
Yes, the MCC code is flawed, in the sense that it is easy to make a mistake and use the code incorrectly. In your case it looks like your printf() function in SendWelcome has filled the eusartTxBuffer so it does not have any more space, so it hangs. The code you have probably expects an ISR to handle actual transmission (if TXIE is set).
 
If you use the software simulator, it seems that the serial port is not very well implemented. At least, I was never able to get it working. It seems that the terminal window just uses a terminal program such as HyperTerm (which only works on XP or maybe Win7), or RealTerm or TeraTerm, which need the actual hardware to work.
 
You should be able to right-click on the project and select "package", to make a zipfile small enough to upload and attach, but with the horribly dysfunctional forum implementation, all bets are off. There was a full moon recently and the "loonies" are still creating havoc at Microchip...

 
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/31 13:42:57 (permalink)
0
I'm wondering if this all stems from my mistaken checking of Enable EUSART Interrupts which I can't unwind.  (If I uncheck it and re-Generate within MCC I get compiler error messages that interrupts are expected by ADC.p1. I've attached a screen grab of the EUSART module in MCC. I see the buffer sizes are set to 8 in eusart.c.
 

/**
Section: Macro Declarations
*/
#define EUSART_TX_BUFFER_SIZE 8
#define EUSART_RX_BUFFER_SIZE 8
/**
Section: Global Variables
*/
volatile uint8_t eusartTxHead = 0;
volatile uint8_t eusartTxTail = 0;
volatile uint8_t eusartTxBuffer[EUSART_TX_BUFFER_SIZE];
volatile uint8_t eusartTxBufferRemaining;
volatile uint8_t eusartRxHead = 0;
volatile uint8_t eusartRxTail = 0;
volatile uint8_t eusartRxBuffer[EUSART_RX_BUFFER_SIZE];
volatile uint8_t eusartRxCount;

 
 

Attached Image(s)

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/31 13:46:54 (permalink)
0
PStechPaul
You should be able to right-click on the project and select "package", to make a zipfile small enough to upload and attach, but with the horribly dysfunctional forum implementation, all bets are off. 





Trying this
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/31 14:11:00 (permalink)
0
And related to EUSART and interrupts, it's not my intention that normal operation wait for keyboard entry here. Rather at any time during normal operation the user can hit 'T' and have the temps displayed to a connected computer. Normal operation should only stop if 'P' is entered and resume once 'X' is entered. I'm still unsure if this is what will happen. 
 

Send_Welcome(); //Send welcome to RS232 connected PC

Keyboard_Input=EUSART_Read(); //Monitor for keyboard instructions
switch(Keyboard_Input){
case 'T':
Send_Temps_DC(Temp_NTC1, Temp_NTC2, Temp_NTC3, Temp_NTC4, Fan1_DC, Fan2_DC);
break;
case 'P':
Program_Constants();
break;
}

if (Not_Over_Heating) //Maintain normal operation of optical switch and timer management

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/31 14:58:37 (permalink)
0
The EUSART_Read() function as implemented will always wait until a new character appears on the serial port. You could do something like:
if (RCIF) { // Proceed only if new character has been received
  Keyboard_Input=EUSART_Read();
  switch(Keyboard_Input) {
    case 'T': Send_Temps();
      break;
    case 'P': Program_Constants();
      break;
    }
  }

I don't know why the last eeprom variable does not get initialized properly. It is probably a bug.

 
Page: << < ..678910.. > >> Showing page 7 of 14
Jump to:
© 2020 APG vNext Commercial Version 4.5