FIRMWARE IMPLEMENTATION
The MPLAB® Code Configurator (MCC) is used to generate the code for the peripherals including the firmware for I/O, Timer1, Analog-to-Digital Converter (ADC), Pulse Width Modulation (PWM), Flash memory and I²C peripherals. The system setup also uses the MCC software. The entire firmware was developed using the MPLAB X IDE. The use of the MCC software is highly recommended since the firmware created is tested and well documented. The initialization and the user routines for each peripheral are modular and in case the user wants to use another larger or smaller PIC16F1XXX device, the re-creation of peripheral routines is very simple and takes very little time. Using the MCC, the code for all the peripherals will be automatically generated and placed in the MPLAB X project. The Adding a Timer explanation shows a step-by-step process for using the MCC to generate code for Timer1 as a brief example.
I²C Slave Interrupt Firmware
The I²C Slave Interrupt Firmware has also been created using MCC. MCC firmware has a built-in example of serial EEPROM communication. The I²C Slave Interrupt details the setup using MCC to modify and incorporate the Slave I²C used in the Power Sequencer program. This method is quick and very easy to use without any prior knowledge or setup details on the I²C protocol or function.
User Application
All code has been written in state machine format. The code for the Power Module (PM) is in the file app.c. The code for the ADC, Flash, Key, and System is in the respective files appAdc.c, appFlash.c, appKey.c, and appSys.c files. The definitions and variables used are defined in app.h. The entire application code is state-machine based, where each task is defined as a series of states. For example, there is a state machine for the ADC, for each PM module, for Flash Memory, and for the overall system. The main.c program is very simple, as shown.
void main(void)
{
//All state machines are initialized at the start
SYSTEM_Initialize();
APP_FLASH_Initialize();
APP_M0_Initialize();
APP_M1_Initialize();
APP_M2_Initialize();
APP_M3_Initialize();
APP_M4_Initialize();
APP_KEY_Initialize();
APP_ADC_Initialize();
APP_SYS_Initialize();
//In an infinite loop each state machine is run one after another
while (1)
{
APP_M0_Tasks();
for (MI=1;MI < AllModules;MI++)
APP_MX_Tasks();
APP_KEY_Tasks();
APP_ADC_Tasks();
APP_SYS_Tasks();
APP_FLASH_Tasks();
}
}
Modules 1 to 4 correspond to the PMs 1 to 4. Module 0 is designated to run a state machine which monitors the Input Voltage.
Each initialize routine initializes the module or the system or the peripheral. On the other hand, each task is a state machine that runs the tasks for the application PM modules 0 to 4, the ADC, Key, Flash Memory, and the overall system.
Parameter Structure for Each Module
Each PM is assigned a set of parameters that are defined in app.h.
The parameters are:
- State: Which defines the state in which each module is in at a given moment in time.
The eight states are:- Init: The Initial state of the Module
- On: Module is in the ON state
- Off: Module is in the OFF state
- Start: Module is turned ON
- Starting: Module rise-time is taken into account when turning ON
- Stop: Module is turned OFF
- UpdatePWM: Module output voltage level is adjusted by the PWM
- ErrorChecking: Module output voltage level is checked to be within error limits
- NormalUVL, NormalOVL, MarginUVL, MarginOVL: OverVoltageLimit and UnderVoltageLimit for Normal and Margin voltages. These variables are used and maintained for error checking. They are 8-bit unsigned value and they can be modified by the user.
- ADC: Unsigned 16-bit value to maintain 16 counts of 10-bit ADC values.
- PWMValue: 10 bit PWM duty cycle value used in the specific PWM used with the Module.
- ADCValue: 8-bit average value of ADC over 16 counts of 10-bit values. This value is compared with the limit voltage values and checked for any errors.
- anChannel: ADC channel number assigned to Module.
- OnTime and OffTime: 14-bit value in mS for the start and stop time for each module
- TurnOn: Bit value to indicate if the module is turned on.
All parameters are defined in a typedef struct and an array of this struct is defined as:
appmData[5]
The appmData[ 1] is for Module 1… appmData[4] is for module 4.
appmData[0] is kept for Input Voltage.
All the states and parameters are not necessarily relevant for the Input Voltage.
i.e., appmData[3].PWMValue corresponds to the 10-bit Duty cycle value of the PWM used for Module 3.
Apart from creating this structure, each module has an Initialize routine and a Tasks routine defined as :
APP_Mx_Initialize()
APP_Mx_Tasks()
Where x is a value 0 to 4.
By creating this structure and the associated functions for each module, it now becomes very easy for the user to increase or decrease the number of modules used in the application. If the number of modules required is three then decrease the number of elements by one (from four to three). One Initialize and Task functions can also be deleted. However, if we need to increase the number of modules by one to five, then the number of elements in the array needs to increase (from four to five). A copy and paste of one additional Initialize and Tasks routine will be needed and the appropriate parameters adjusted to reflect the new Module 5.
Adding a Code Module is an example of how to add one additional Module 4 in the application.
ADC Routine and Voltage Measurement
The ADC routine essentially runs thru and sample the voltage of each module 0 to 4. Module 0, as mentioned earlier, corresponds to the Input Voltage, which always gets monitored for failure. A failure of the Input Voltage also causes a shutdown. No retries will be attempted.
The 10-bit ADC routine samples each voltage 16 times and then uses the averaged 8-bit value to check for an error or adjustment of the margin voltage. In this application, the Voltage reference is 5.0 V or Vdd of the system. Using 5.0 V as a voltage reference will work fine when sampling and converting 1.8 V, 2.5 V, and 3.3 V Modules. However, for the 5.0 V module and the Input Voltage, a resistor divider is needed to bring the full voltage range within the 5.0 V reference voltage. The resistor divider factor for the 5.0 V Module is 0.55 and the Input Voltage divide factor is 0.239. Users will have to use these values during the calculation of the under and over voltage limit values and define them appropriately in the header files. This is especially required if the user decides to use values other than those used in this application note.
ADC State Machine States
The ADC state machine states are:
- Init: Initializes the ADC converter
- Sample: In this state, the ADC channel is assigned and a 1 ms Sampling time is allowed before the conversion is started.
- Convert: The convert command is given and the ADC conversion is started
- Done: a check to see if the conversion is done. If yes, then the converted value is added and if all 16 samples have been taken, the appropriate module state is assigned for a PWM update and voltage check.
- Next: In this state, the next module is assigned to the ADC and the whole process is repeated.
The ADC state machine is always running. A designated Module Voltage is only checked if that module is turned ON or in the ON state. Otherwise, only the Input Voltage is checked. Once a module is turned ON, it is always checked.
Key State Machine
The Key state machine has the following states:
- Init: Initializes the State machine
- High: When the key is at the default high state, a check for a key press (0 volts) is done
- Low: When the key is in the pressed state, a check for a release (5 volts) is done
- Debounce: In this state, a delay of 20 ms is executed then a check for a high or low state is done
The Key state machine ensures the proper functioning of the key press switch S1. If the system is OFF, a key-press will turn the system ON. If the system is ON, a key-press will turn the system OFF.
SYS State Machine
The SYS state machine manages the overall functioning of the system. In particular, it manages failure modes during startup. If a startup failure occurs, then automatic re-starts are executed as defined by the user in the Retry parameter. The APP_SYS_Tasks() routine makes sure that all the retry attempts are executed. If all retry attempts are exhausted, the system will shut down and a fault condition will result. The user must then clear the system using a serial command on the I²C interface or a button on the Graphical User Interface (GUI). Any failure mechanism must be fixed to prevent another failure during startup. The system will not restart until the reset command is executed or a power-down reset is done.
The SYS states are:
- Init: Initialize state for SYS
- ON: State when the system is ON
- OFF: State when the system is OFF
- Starting: State when the system is starting up
- Stopping: State when the system is shutting down
- Fault: State when a system fault has occurred
Flash State Machine
The default parameters are saved in Flash Memory of the PIC16F1509. The Flash PM storage location starts at 0x1f80 and the parameters are saved sequentially for each module.
The default parameters for each Module are:
- Start time
- Stop time
- Normal Under Voltage limit
- Normal Over Voltage limit
- Margin Under Voltage limit
- Margin Over Voltage limit
- PWM DutyCycle
- Apart from these 28 parameters( 4 x 7), the System parameters are also saved:
- Vin Under Voltage limit
- Vin Over Voltage limit
- Number of retries
The user can use the GUI or serial command to change the value of these parameters. These values have to be “burned” on to Flash Memory by the user, using the Burn Flash button on the GUI or the serial command: 0x10, 0xAB. Once they are burned, they become the new default values. The flash.as file defines all the default values and locations in Flash PM.