Hello,
I am trying to make firmware code for a SCR controller.
Need to work how I can make my 8 analog input voltage to ADC and generate PWM (for R,S,T phase) considering zero crossing and firing angle correction.
Few information are follows.
1. I need to use pin ADCIN_A0 to ADCIN_B1. Here ADCIN_A1 and ADCIN_A3 should be exclude, because I am ignoring AC current and voltage part.(see the schematic)
2. My input DC_volt_ADC and DC_current_ADC signals are 0-3 volt and 20mA . Which might be single ended input.
3. If you look in the schematic Spare2_ADC, Spare1_ADC, Voltage_control signals are depends on M_Select_1, M_Select_2, M_Select_3(external Relay controlled) in I/O pin 77-89.
4. The switching logics are,(
When M_Select_1--> HIGH ,Voltage_control -->HIGH and others (Spare2_ADC, Spare1_ADC) are LOW..
At this time M_Select_2, M_Select_3 are LOW.
Alternatively, M_Select_2, M_Select_3 pins could be HIGH when M_Select_1 is kept LOW thus Spare2_ADC, Spare1_ADC would be HIGH.
5. 3.3V REF Voltage_ADC is applied to ADCIN_A7 to ADCIN_B1.
I am following this code ( some part of it from ATmel ).
Kindly help me to write code in the required logic.
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
interrupt void adc_isr(void);
// Global variables used in this example:
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 Voltage1[10];
Uint16 Voltage2[10];
Uint16 Voltage3[10];
Uint16 Voltage4[10];
Uint16 Voltage5[10];
Uint16 Voltage6[10];
Uint16 Voltage7[10];
Uint16 Voltage8[10];
Uint16 Voltage9[10];
main()
{
InitSysCtrl();
EALLOW;
#if (CPU_FRQ_150MHZ) // Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
#endif
EDIS;
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK;
EDIS;
DINT;
Gpio_select();
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EALLOW; // This is needed to write to EALLOW protected register
PieVectTable.ADCINT = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
InitAdc(); // For this example, init the ADC
AdcRegs.ADCTRL1.all = 0;
AdcRegs.ADCTRL1.bit.ACQ_PS = 7;
AdcRegs.ADCTRL1.bit.SEQ_CASC =1;
AdcRegs.ADCTRL1.bit.CPS = 0;
AdcRegs.ADCTRL1.bit.CONT_RUN = 0;
AdcRegs.ADCTRL2.all = 0;
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 =1;
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0;
AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;
AdcRegs.ADCMAXCONV.all = 0; // 8 double conv's (16 total)
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;// Setup ADCINA0 as 1st SEQ1 conv
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1;//Setup ADCINA1 as 2nd SEQ1 conv
EPwm2Regs.TBCTL.all = 0xC030;
EPwm2Regs.TBPRD = 2999;
EPwm2Regs.ETPS.all = 0x0100;
EPwm2Regs.ETSEL.all = 0x0A00;
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
LoopCount = 0;
ConversionCount = 0;
asm(" RPT #10 || NOP"); // Short delay for ADC reset to take effect
void configure_adc_voltage(void)
{
struct adc_config conf_adc;
adc_get_config_defaults(&conf_adc);
conf_adc.reference = ADC_REFERENCE_INT3V;
conf_adc.positive_input = ADC_POSITIVE_INPUT_VOLTAGE;
conf_adc.negative_input = ADC_NEGATIVE_INPUT_GND;
conf_adc.sample_length = ADC_VOLTAGE_SAMPLE_LENGTH;
adc_init(&adc_instance, ADC, &conf_adc);
ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4;
adc_enable(&adc_instance);
}
float calculate_voltage(uint16_t raw_code)
{
float VADC; /* Voltage calculation using ADC result for Coarse voltage calculation */
float VADCM; /* Voltage calculation using ADC result for Fine voltage calculation. */
float INT3VM; /* Voltage calculation for reality INT3V value during the ADC conversion */
VADC = ((float)raw_code * INT3V_VALUE_FLOAT)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
/* Coarse Temp Calculation by assume INT1V=1V for this ADC conversion */
coarse_voltage = voltageR + (((voltageH - voltageR)/(VADCH - VADCR)) * (VADC - VADCR));
/* Calculation to find the real INT1V value during the ADC conversion */
INT3VM = INT3VR + (((INT3VH - INT3VR) * (coarse_voltage - voltageR))/(voltageH - voltageR));
VADCM = ((float)raw_code * INT1VM)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
/* Fine Temp Calculation by replace INT3V=3V by INT3V = INT3Vm for ADC
conversion */
fine_voltage = voltageR + (((voltagepH - voltageR)/(VADCH - VADCR)) * (VADCM - VADCR));
return fine_voltage;
}
// Mux input
int16_t adcReadData(uint16_t mux)
{
#if defined(__AVR_AT90USB162__)
return 0;
#else
uint16_t low;
ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC
ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode
ADMUX = aref | (mux & 0x1F); // configure mux input
ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion
while (ADCSRA & (1<<ADSC)) ; // wait for result
low = ADCL; // must read LSB first
return (ADCH << 8) | low; // must read MSB only once!
#endif
}
float adc_value, inst_current;
float acc_load_current; // accumulator = (I1*I1 + I2*I2 + ... + In*In)
double rms_current;
// Calculate the real instantanous value from the ADC reading
inst_current = (adc_value/1024)*2.5; // 10bit ADC, Voltage ref. 2.5V, so formula is: x=(adc/1024)*2.5V
// Update the RMS value with the new instananous value:
// Substract 1 sample from the accumulator (sample size is 512, so divide accumulator by 512 and substract it from the accumulator)
acc_load_current -= (acc_load_current / 512);
inst_current *= inst_current; // square the instantanous current
acc_load_current += inst_current; // Add it to the accumulator
rms_current = (acc_load_current / 512); // Get the mean square value. (sample size is 512)
rms_current = sqrt(rms_current); // Get RMS value
// Now the < rms_current > is the real RMS current
// Clear SampleTable
for (i=0; i<BUF_SIZE; i++)
{
SampleTable[i] = 0;
}
// Start SEQ1
AdcRegs.ADCTRL2.all = 0x2000;
for(;;)
{ // Take ADC data and log them in SampleTable array
// Initialize the array index. This points to the current
// location within the SampleTable
array_index = 0;
for (i=0; i<(BUF_SIZE/16); i++)
{
// Wait for int1
while (AdcRegs.ADCST.bit.INT_SEQ1== 0){}
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // Set GPIO34 for monitoring -optional
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
// Wait for ADC interrupt
for(;;)
{
LoopCount++;
}
}
interrupt void adc_isr(void)
{
Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
Voltage3[ConversionCount] = AdcRegs.ADCRESULT2 >>4;
Voltage4[ConversionCount] = AdcRegs.ADCRESULT3 >>4;
Voltage5[ConversionCount] = AdcRegs.ADCRESULT4 >>4;
Voltage6[ConversionCount] = AdcRegs.ADCRESULT5 >>4;
Voltage7[ConversionCount] = AdcRegs.ADCRESULT6 >>4;
Voltage8[ConversionCount] = AdcRegs.ADCRESULT7 >>4;
Voltage9[ConversionCount] = AdcRegs.ADCRESULT8 >>4;
// If 40 conversions have been logged, start over
if(ConversionCount == 9)
{
ConversionCount = 0;
}
else ConversionCount++;
// Reinitialize for next ADC sequence
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit
AdcRegs.ADCTRL2.bit.RST_SEQ2 = 1; // Reset SEQ1
AdcRegs.ADCST.bit.INT_SEQ2_CLR = 1; // Clear INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;
}(Please visit the site to view this file)