Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
April 20, 2024, 01:16:50 13:16


Login with username, password and session length


Pages: [1]
Print
Author Topic: DSPic30F4012 Cycle time measurement with 133Hz software PWM  (Read 3441 times)
0 Members and 1 Guest are viewing this topic.
younder
Newbie
*
Offline Offline

Posts: 11

Thank You
-Given: 26
-Receive: 7


« on: September 26, 2015, 07:15:46 19:15 »

Hi Everyone!

I've been testing the DSPic30F4012 on a trip computer for my 4WD for a while. I could not use HW PWM due to EXT_INT0, 1 & 2 (are being used by RPM, Speed and fuel flow meter). So I decided to study software PWM. Yes, I know it may not be a good idea for high frequencies like i.e. > 100Hz, however, I decided to test it and measure the cpu cycle time to compare the performance @ different frequencies.

Below is the test code, with software PWM by Ttelmah & PCM_Programmer.

The point is that, even with my full code, It did not show the CPU to be overloaded when I increase the timer 3 frequency from 1Khz to 4Khz or even more. Is it because of the 30MIPS? Or at this rate it shouldn't affect anyway?

Longest cpu cycle time Software PWM @ 66Hz (Timer 3 Period = 500uSec): 0,005277s
Longest cpu cycle time Software PWM @ 133Hz (Timer 3 Period = 250uSec): 0,005294s

CCS Version: 5.049

Any comments would be appreciated!!
Hugo

Custom_Fct.h
Code:
unsigned int i,Temp0;
// =============================================================
// "Timer1 ISR", -> called every 568,888mSec <-
// =============================================================
Unsigned int1 Cycle_Time_Overflow=0;
Unsigned int16 Cycle_Time=0,Cycle_Time_Mem[2]={0,0};
Unsigned int32 Cycle_Time_Total=0,Cycle_Time_Max=0;
#INT_TIMER1            
void timer1()        
  {
        Cycle_Time++;
        Cycle_Time_Overflow=1;
  }
// *************************************************************
// =============================================================
// "Timer2 ISR", -> called every 25ms <-
// 117,964,800 as the oscillator internal (Tosc) rate.
// Divide by 4 to get the timer increment rate (Tclk), so 29,491,200 Hz.
// Divide by 64 since the divide by 64 pre-scaler was set, so 460,800 counts / sec on the timer.
// The timer is set to 54,015 (65,536-11,520), so it will overflow after 11,520 counts.
// (1/460,800)*11,520=0,025s or 25ms.
// set_timer2(54,015 + get_timer2()) Timer2 will overflow every 25ms...
// =============================================================
union pulse_data_type {  
   int8 buffer;
   int1 clock[8];
   struct {
      int1 _25;
      int1 _50;
      int1 _100;
      int1 _200;
      int1 _500;
      int1 _1000;
   } mSec;
};
 union pulse_data_type pulse=0;

#INT_TIMER2
void timer2()            
{
  static int8 counter_SP[6] = {1,2,4,8,20,40}; //Counters Setpoint (Value*25ms)
  static int8 i, counter[6] = {1,2,3,4,5,6}, mask;

 // set_timer2(54015 + get_timer2()); //11520counts = 25mSec
  mask=1;
  for (i=0;i<6;i++)
  {
      counter[i]--;
     if (counter[i]==0)
     {
        counter[i]=counter_SP[i];
        pulse.buffer^=mask;
     }
     mask*=2;
  }
}
// *************************************************************
// =============================================================
// Rising/Falling edge pulses
// =============================================================
union edge_data_type {  
   int1 buffer[8];
   struct {
      int1 _25;
      int1 _50;
      int1 _100;
      int1 _200;
      int1 _500;
      int1 _1000;
   } mSec;
};
 union edge_data_type R_Edge={0,0,0,0,0,0,0,0};

 typedef struct Edge_scan {
 int1 scan[8];
 };
 
union edge_scan_type {
 struct Edge_scan Buffer[6];
 struct {
      int1 _25_scan[8];
      int1 _50_scan[8];
      int1 _100_scan[8];
      int1 _200_scan[8];
      int1 _500_scan[8];
      int1 _1000_scan[8];
   } mSec;  
};  
   union edge_scan_type Edge={0,0,0,0,0,0};
    
void Edge_Pulses()            
{
static int1 aux_R[6];     //Auxiliar Variable
static int8 Scan_Count[6]={0,0,0,0,0,0};

  for (i=0;i<6;i++)
  {
//Rising edge
   if (pulse.clock[i]) { //If pulse is true    
         if (aux_R[i]==0) R_Edge.buffer[i]=1; else R_Edge.buffer[i]=0; //and aux is false then edge=TRUE for only one scan
         aux_R[i]=1; //Next scan edge pulse will be false
      } else aux_R[i]=0,R_Edge.buffer[i]=0; //Clear aux till next rising edge detection

//Edge array bits
            if (Edge.Buffer[i].scan[Scan_Count[i]]) {
            if (Scan_Count[i]<7) Edge.Buffer[i].scan[Scan_Count[i]+1]=1;              
               Edge.Buffer[i].scan[Scan_Count[i]]=0;
                  Scan_Count[i]++;
                     if (Scan_Count[i]>7) Scan_Count[i]=0;
      }
         if (R_Edge.buffer[i] && (Scan_Count[i]==0)) Edge.Buffer[i].scan[0]=1;    
  }
}

// *************************************************************

// =============================================================
// A/D Function
// =============================================================
Long Read_AD(int Channel)
  {
  Static Long Analog_Value;
  Switch(Channel)
    {
    case 0 : input(BAT_VOLTAGE), setup_adc_ports(sAN0, VSS_VDD); break;
    case 1 : input(ALTERNATOR_CURRENT), setup_adc_ports(sAN0 | sAN1, VSS_VDD); break;
    case 2 : input(FUEL_TANK_LEVEL), setup_adc_ports(sAN0 | sAN1 | sAN2, VSS_VDD); break;
    case 3 : input(COOLANT_TEMP), setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3, VSS_VDD); break;
    case 4 : input(AIR_TEMP), setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3 | sAN4, VSS_VDD); break;
    default: return(0);
    }
  set_adc_channel(channel);
  Analog_Value = read_adc();
  setup_adc_ports(NO_ANALOGS);
  return(Analog_Value);
  }
// *************************************************************

Test.c
Code:
#include <30F4012.h>
#device ADC=10    
#fuses FRC_PLL16,NOPROTECT,NOWRT,MCLR,BORRES,PUT64,NOCKSFSM,BORV27,NODEBUG,NOWDT
#use delay(Internal=117964800) // Internal 7.3728Mhz * FRC_PLL16 = 117964800Hz (30MIPS)
#use i2c(MASTER, SCL=PIN_F3, SDA=PIN_F2, FAST, stream=I2C_SOFTWARE)
#build (stack=256) // 128,256,384 or 512 depending how big the code is

//PORT B
#define BAT_VOLTAGE           PIN_B0  //AD0 - 12V battery level
#define ALTERNATOR_CURRENT    PIN_B1  //AD1 - Alternator´s current
#define FUEL_TANK_LEVEL       PIN_B2  //AD2 - Fuel tank level
#define COOLANT_TEMP          PIN_B3  //AD3 - Coolant Temperature
#define AIR_TEMP              PIN_B4  //AD4 - Internal Air Temperature
#define KEY_BIT_1             PIN_B5  //IN - Key Bit 01

//PORT C
#define KEY_BIT_2             PIN_C13  //IN - Key Bit 02
#define KEY_BIT_3             PIN_C14  //IN - Key Bit 03
#define LED_OUT               PIN_C15  //OUT - LED

//PORT D
#define GAS_FLOW_IN           PIN_D0  //INT1 - Gasoline Flow Pulse
#define SPEED_IN              PIN_D1  //INT2 - Speed Sensor pulse

//PORT E
#define AUX_01_OUT            PIN_E0  //OUT - Auxiliar Output 1 (PWM 1)
#define AUX_02_OUT            PIN_E1  //OUT - Auxiliar Output 2 (PWM 2)
#define RELAY_01_OUT          PIN_E2  //OUT - Relay #01
#define RELAY_02_OUT          PIN_E3  //OUT - Relay #02
#define AUX_01_IN             PIN_E4  //IN - Auxiliar Input 1
#define AUX_02_IN             PIN_E5  //IN - Auxiliar Input 2
#define RPM_IN                PIN_E8  //INT0 - Tachometer Pulse
#use FIXED_IO( E_outputs=PIN_E0,PIN_E1,PIN_E2,PIN_E3 )

#include <lib\i2c_Flex_LCD.h>
#include <lib\Custom_Fct.h>

#define PWM_PIN  PIN_E2
#define PWM_PIN2  PIN_E3
#define LOOPCNT 29

// =============================================================
// Global variables declaration
// =============================================================
Unsigned int16 ADC_0=0,ADC_1=0,ADC_2=0,ADC_3=0,ADC_4=0,Key;
Unsigned int8 width, width2;
int1 first_scan_bit=1,Edge_new_screen=1,UP_Key, DOWN_Key, ENTER_Key;

#int_timer3
void timer3_isr(void)
{
static int8 loop = LOOPCNT;
static int8 pulse,pulse2;

if(--loop == 0) {
   loop = LOOPCNT;
   pulse = width;
   pulse2 = width2;
  }

if(pulse) output_high(PWM_PIN), pulse--; else output_low(PWM_PIN);
if(pulse2) output_high(PWM_PIN2), pulse2--; else output_low(PWM_PIN2);
}

void Initialization() {
//Disable all interrupts
   disable_interrupts(INTR_GLOBAL);
// Initialize 20x4 LCD Display
   lcd_init();
//Configures Timer1
   setup_timer1 (TMR_INTERNAL | TMR_DIV_BY_256, 65535); //Configures timer1 to overflow every 568,888mSec
   enable_interrupts(INT_TIMER1);
//Configures Timer2
   setup_timer2 (TMR_INTERNAL | TMR_DIV_BY_64, 11520); //Configures timer2 to overflow every 25mSec
   enable_interrupts(INT_TIMER2);
//Configures Timer3
   setup_timer3 (TMR_INTERNAL | TMR_DIV_BY_1, 7500); //7500counts = 250uSec  
   enable_interrupts(INT_TIMER3);  
//ADC clock
   setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_8);
//Set GIE&PEIE bits and Enable all interrupts
   enable_interrupts(INTR_GLOBAL);
 }

void LCD_Display_Diag()
  {
         if (Edge.mSec._50_scan[0])  {
                  lcd_gotoxy(1, 1);
                  printf(LCD_PUTC,"Actual Cycle:");
                  lcd_gotoxy(1, 2);
                  printf(LCD_PUTC,"%1.6lws",Cycle_Time_Total/100);
         }
          if (Edge.mSec._100_scan[1])  {                
                  lcd_gotoxy(1, 3);
                  printf(LCD_PUTC,"Longest Cycle:");
                  lcd_gotoxy(1, 4);
                  printf(LCD_PUTC,"%1.6lws",Cycle_Time_Max/100);
                  }
   }

long KeyScan() {    
static long inKey=0, key_mem=0;
#bit  inKey_bit0 = inKey.0      
#bit  inKey_bit1 = inKey.1  
#bit  inKey_bit2 = inKey.2  

      If (input(KEY_BIT_1)) {
      if (!UP_Key) delay_ms(20);          //debouncing time
      UP_Key=1;
      inKey_bit0=1;
      } else UP_Key=0,inKey_bit0=0;
      
      If (input(KEY_BIT_2)) {
      if (!DOWN_Key) delay_ms(20);        //debouncing time
      DOWN_Key=1;
      inKey_bit1=1;
      } else DOWN_Key=0,inKey_bit1=0;
      
      If (input(KEY_BIT_3)) {
      if (!ENTER_Key) delay_ms(20);       //debouncing time
      ENTER_Key=1;
      inKey_bit2=1;
      } else ENTER_Key=0,inKey_bit2=0;
 
    if(inKey != key_mem){
       key_mem=inKey;
       return inKey;
    } else return 0;
 }

void PWM() {
static int8 cnt=0, cnt2=0;
static int1 dup=1, ddown=1;
//PWM 1
If (Edge.mSec._25_scan[1]) {
   if (dup) cnt++; else cnt--;
   if (cnt>29) dup=0;
   if (cnt==0) dup=1;
      width = cnt;
   }

//PWM 2
If (Edge.mSec._50_scan[2]) {
   if (ddown) cnt2++; else cnt2--;
   if (cnt2>29) ddown=0;
   if (cnt2==0) ddown=1;
      width2 = cnt2;
 }  
}

void AD() {
static int8 Read_Analog=0;

 Read_Analog++;
if (Read_Analog>4)Read_Analog=0;
Switch(Read_Analog)
  {
    case 0 : {
               ADC_0=Read_AD(0);
             } break;      
    case 1 : {
               ADC_1=Read_AD(1);
             } break;  
    case 2 : {
               ADC_2=Read_AD(2);  
             } break;
    case 3 : {
               ADC_3=Read_AD(3);  
             } break;
    case 4 : {
               ADC_4=Read_AD(4);  
             } break;
  }
}

void Cycle_time_measuring()
{
static int1 Flag_ResetCycleTime=0;
static int8 Reset_Cycle_Time=0;
static unsigned int16 Cycle_Time_Buffer=0;

         Cycle_Time_Buffer=Cycle_Time;
         Cycle_Time_Mem[0]=get_timer1(); //get actual tmr1 value
         if ((Cycle_Time_Mem[0]==65535) && Cycle_Time_Overflow) Cycle_Time_Mem[0]=0,Cycle_Time_Overflow=0;
               if (Cycle_Time_Mem[0]>Cycle_Time_Mem[1])
                  {
                     Temp0=Cycle_Time_Mem[0]-Cycle_Time_Mem[1]; //how many tmr1 counts since last measuring?
                     Cycle_Time_Total=((((int32)Cycle_Time_Buffer*65535)+Temp0)*868);  
                  }
               else
                  {  
                     if (Cycle_Time_Buffer<=0) Temp0=1; else Temp0=Cycle_Time_Buffer;
                     Cycle_Time_Total=((((int32)Temp0*65535)-Cycle_Time_Mem[1]+Cycle_Time_Mem[0])*868);  
                  }
                     Cycle_Time_Mem[1]=Cycle_Time_Mem[0]; //memorizes current tmr1 value in case a new interrupt happens before tmr1 overflows
                     Cycle_Time=0;   //Reset Actual Cycle time counter

         if (Cycle_Time_Total>Cycle_Time_Max) Cycle_Time_Max=Cycle_Time_Total;
        
         //Reset Longest Cycle Time

            If (ENTER_Key) Flag_ResetCycleTime=1;
               If (!ENTER_Key && Flag_ResetCycleTime && R_Edge.mSec._50) Reset_Cycle_Time++;
                 if (Reset_Cycle_Time>=10) {
                 Flag_ResetCycleTime=0;
                 Reset_Cycle_Time=0;
                 Cycle_Time_Max=0;
     }
 }

void Main() {
  Initialization();
   while(1){
  
  Edge_Pulses();           //Edge pulses pulses for general use
  Key=keyScan();           //Up, Down and Enter Keys
  Cycle_time_measuring();  //At this point, measure actual and longest cycle time
  AD();                    //Just read AD ports
  PWM();                   //Perform a Software 4Khz PWM (Timer 3 @ 250uSec)
  LCD_Display_Diag();      //Display measured values
  
  }
}
//------------------ EOF ---------------------


« Last Edit: September 27, 2015, 12:24:08 00:24 by younder » Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC