Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

writing random numbers in PIC16F1936 Internal EEPROM

Status
Not open for further replies.
I understand the logic on phases control but the problem is to make up those in MicroC for phase shifting for the moment I am getting three signals on P1A,P1B and P1C but those are in phase,please help with codes;the sine table values were extracted from another post on a forum where the values were used in AVR types but there was no codes.

Please show m how the Timer is used to deal with those phase shift and counting 1/3 for each phase.

Thank you
 

You asking me to explain you algebra while you know nothing about arithmetics. No one will provide you complete code. It is your task and we able to only guide you. As I mentioned before, sine table should be stored in flash, have same relosultion as your pwm has (8/10/12 bit) and only then timer should be impemented for interrupt routine which will realize phase shift. I can give you a small hint also - all pwm generation are based on interrupts because of maximum priority. For 50 Hz 8 bit PWM timer should work in frequency 256 * 50 = 12800 Hz. For 10 bit PWM frequency should be 51200 Hz and unsigned int type should be used.
MicroC - is just a C compilier. The same code will work the same way on other compiliers and even other MCU. Don't stuck on PICs or AVRs. There are a lot of powerfull and cheap microcontrollers available in a world.
 

But,I think the role of forum is helping each other,I don`t know how to setup the interrupt for fulfilling the stated task,that is what I am asking.

Regards,
 

Here are the codes I have now in trying to shift the table for phase shifting implementation,I have 32 values in the table,can anybody help on handling when compiling there is no error but I simulate with proteus I fon`t see the phase shift of the three signals I have,could you help to manage?
PHP:
 sbit UP at RB5_bit; sbit DOWN at RB4_bit;
        //const signed char sine_table[33] = {0,24,48,69,88,104,115,123,125,123,115,104,88,69,48,24,0,-24,-48,-69,-88,-104,-115,-123,-125,-123,-115,-104,-88,-69,-48,-24,0,};
          const signed char sine_table[]={0, 25, 49, 73, 96, 118, 139, 159, 177, 193, 208, 220, 231, 239, 245, 249, 250, 249, 245, 239, 231, 220, 208, 193, 177, 159, 139, 118, 96, 73, 49, 25};

         unsigned short new_DC,xx,yy,bb, newduty;
              char t,ii;
              unsigned char DUTY_CYCLE;
              unsigned int TBL_POINTER_NEW1,TBL_POINTER_NEW2,TBL_POINTER_NEW3, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ;
              
    void debounce()
            {
             delay_ms(300);
            }
            void interrupt()
            {
               if(TMR2IF_bit==1)
               {
                 TBL_POINTER_NEW1=TBL_POINTER_OLD;
                if(TBL_POINTER_NEW1<TBL_POINTER_OLD)
                {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                  TBL_POINTER_SHIFT = TBL_POINTER_NEW1 >> 11;
                }
                  TBL_POINTER_NEW1=sine_table[11];
                  
                  if(TBL_POINTER_NEW1<TBL_POINTER_OLD)
                  {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                  TBL_POINTER_SHIFT = TBL_POINTER_NEW2 >> 11;
                  }
                    TBL_POINTER_NEW2=sine_table[22];
                      if(TBL_POINTER_NEW2<TBL_POINTER_OLD)
                  {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                   TBL_POINTER_SHIFT = TBL_POINTER_NEW2 >> 11;
                  }

                DUTY_CYCLE = TBL_POINTER_SHIFT;
                CCPR1L = sine_table[DUTY_CYCLE];
                TMR2IF_bit = 0;
               
                       }
                       
                       }
                  /*
                  PWM1_set_duty(sine_table[newduty]);
                  if(newduty=sine_table[newduty]+11)
                  {
                   PWM1_set_duty(sine_table[newduty]+11);
                  }
                  else
                  PWM1_set_duty(sine_table[newduty]+22);
                  INTCON.TMR2IF=0;
               }
               }    */

            
 void main()
 {
   TRISA=0XFF;
   TRISC=0XF0;
   TRISB=0XF8;
   CCP1CON=0X0C;
   PSTR1CON=0X1F;
   DUTY_CYCLE = 0;
   PR2=249;
   T2CON=4;
   T2CON.TMR2ON=1;
   T2CON.TMR2ON=1;
   TMR2IF_bit=0;
   while(TMR2IF_bit==0)
   {
   TMR2IF_bit=0;
   TMR2IE_bit=0;    //Enable Timer 2 Interrupr
   GIE_bit=1;     //Enable Global interrupt
   PEIE_bit=0;    //disable all peripheral interrupt
 //PWM1CON=    For dead time programming
 }
   PWM1_init(15000);      //Initialise PWM at 15KHZ
while(1){
    new_dc=0;   
       if(!(PORTA.B5)){
      debounce();
      if(new_dc<249)
      new_dc=new_dc+5;   //increment duty cycle
      }
       if(!PORTA.B4){
      debounce();
      if(new_dc!=0)
      new_dc=new_dc-5; //decrement duty cycle
           }
           if(newduty!=new_dc)
           {
           newduty=new_DC;
            PWM1_Start();
           //PWM1_set_duty(sine_table[newduty]) ;
            }
          }
        }
,Thanks.
 

It's almost mysterious what you are doing in your code. We would expect three PWM units to be used with different duty cycle for the three output phases, loaded with phase shifted table values at each interrupt, but there's only one. The table pointer (and it's two phase shifted copies) would be slowly rotating through the sine table according to the motor speed, but TBL_POINTER_OLD is only set to zero and never increased.

There are additional conceptual errors. In a three phase bridge, a pwm duty cycle of 0.5 corresponds to zero output voltage, 0.0 to maximum negative and 1.0 to maximum positive output voltage. The sine table should be designed respectively.

Finally a point that should be place back for the time being. To achieve full output voltage in a three phase inverter, the waveform per phase can't be a pure sine, instead it's balanced towards higher modulation index by an superimposed common mode voltage, e.g. a triangle wave of threefold frequency.
 

I may be wrong, but seems like the PIC16F1936 being able to deal with just 2 phases, not 3. According to datasheet it has just two PWM modules, therefore you should seek for another option to do that by hardware.
 

When you use ECCP capabilities you can handle more and get multiple output of PWM signals,with my codes above I am getting 3 signals at P1A,P1B,and P1C.those PWM signals has the same parameters.
 

I sense a lack of understaning of 'C' in general.

The variable prefix 'unsigned' is a way of telling the compiler that the named variable following it uses all the bits to store the value instead of reserving one bit for the sign (+ or -). It follows that by declaring it as an unsigned array, you can not put negative numbers in it. What you can do, and it makes more sense anyway because the PWM generator only handles positive numbers, is offset all the values so they are centered on 127 (half of the maximum an unsigned char can hold). So instead of going positive and negative around zero, the values go between 0 and 254 and are always positive.

There is no "phase shift" in the software. What you have to do is produce three single phase PWM signals using three PWM modules or else some clever simulation of them in software. Each value in the table produces a different duty cycle (=voltage) from the PWM module and there should be a value for each point along the sine wave you want to produce the voltage for. The same table can be used for all three PWM generators, you get the effective difference in their phase by reading different values for each from the table. The PWM generator for phase 1 reads from place 'x' and phases 2 and 3 read from places 'x + 1/3' and 'x + 2/3 ' of the table length. When the end of the table is reached, you wrap around to the begining again.

The method of symetry mentioned earlier is just a way of shortening the table by using some math routines. There is nothing stopping you using one big table or even three different tables, one for each phase but you can save space by recognising that a sine wave has symetry around two points. The minimum you need to put in your table is the values for one quadrant (say 0 - 90 degrees). Scale the values in the table between 0 and 127 for angles 0 - 90 degrees. The first quadrant PWM values are the values in the table + 127. You can get the second quadrant by reversing the order you read the values from the table and adding 127. Then you repeat the first and second quadrants but instead of adding 127, you subtract the table value from 127. The result is a full sine wave but with only 1/4 of the values being needed. There is no big saving if you are only using 33 values in the whole table (post #17) but you would get a very distorted waveform with so few values (only 10 points per cycle). You would do better to use many more values and the symetry trick to save space.

Brian.
 

I hope the good sine table might be the one of post #5 where it is up to 123,the logic I get it but the problem I have had is to implement the same in codes,MicroC or CCS C ,I used to read the AN 889 from Microchip but I don`t understand some terms so that makes me to not understand all the codes,please could you convert what you said in codes so that you show me.

With proteus simulation I ma getting three PWM the remaining is to shift them as you said and that is the one very complicated for me,
furthermore is the phase shifting visible in case I simulate with proteus?

Thank you.
 

It's not possible to generate phase shifted pwm signals with a single CCP unit, instead you have to use all three CCP1, CCP2 and CCP3. I would also utilize the dead-time generator and have use PWM pins in total, but that's not absolutely necessary.
 

Perhaps it is not possible to use one ECCP Module,my self I can handle that issue of PWM generation whatever ECCP Modules used but what about shifting of 120 degrees I have been asking?can you help me to handle?
Thank you!!
 

Logically, you'll add an 120/240 degree offset to the pointer and take the value modulo 360 degree. The degree value has to be scaled to the actual table size and quadrant representation.
 

Dear FvM,
The problem is how those operations will be fulfilled in codes about the theory I understand very well how to deal with.

Please help with codes,the logic implementation is understandable.

Thank you
 

Hi,

where exactely is the problem? I don´t understand.
In post#6 i wrote an example. I don´t think it is difficult to use the syntax of your compiler, nor is it difficult to replace my variiable names with your variable names, nor is it difficult to use your values instaed of mine.
The result is to have three independent pointer for a single sine table giving three phases with 120 degree shift, each.

Write the code and show it to us.

Klaus
 

Dear KlausSt,

see my codes,I was trying to follow what you said on post #6
Code:
sbit UP at RB5_bit; sbit DOWN at RB4_bit;
        const signed char sine_table[33] = {0, 3, 7, 10, 13, 16, 20, 23, 26, 29, 33, 36, 39, 42, 46, 49, 52, 55, 58, 62, 65, 68, 71, 74, 77, 80, 83, 87, 90, 93, 96, 99, 102, 105, 108, 111, 113, 116, 119, 122, 125, 128, 131, 133, 136, 139, 142, 144, 147, 150, 152, 155, 157, 160, 162, 165, 167, 170, 172, 174, 177, 179, 181, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 211, 213, 215, 217, 218, 220, 221, 223, 224, 226, 227, 228, 230, 231, 232, 233, 235, 236, 237, 238, 239, 240, 241, 241, 242, 243, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 242, 241, 241, 240, 239, 238, 237, 236, 235, 233, 232, 231, 230, 228, 227, 226, 224, 223, 221, 220, 218, 217, 215, 213, 211, 210, 208, 206, 204, 202, 200, 198, 196, 194, 192, 190, 188, 186, 184, 181, 179, 177, 174, 172, 170, 167, 165, 162, 160, 157, 155, 152, 150, 147, 144, 142, 139, 136, 133, 131, 128, 125, 122, 119, 116, 113, 111, 108, 105, 102, 99, 96, 93, 90, 87, 83, 80, 77, 74, 71, 68, 65, 62, 58, 55, 52, 49, 46, 42, 39, 36, 33, 29, 26, 23, 20, 16, 13, 10, 7, 3};

          

         unsigned short new_DC,xx,yy,bb, newduty;
              char t,ii;
              unsigned char DUTY_CYCLE;
              unsigned int TBL_POINTER_NEW1,TBL_POINTER_NEW2,TBL_POINTER_NEW3, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ;
              
    void debounce()
            {
             delay_ms(300);
            }
            void interrupt()
            {
               if(TMR2IF_bit==1)
               {
                 TBL_POINTER_NEW1=TBL_POINTER_OLD;
                if(TBL_POINTER_NEW1<TBL_POINTER_OLD)
                {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                  TBL_POINTER_SHIFT = TBL_POINTER_NEW1 >> 11;
                }
                  TBL_POINTER_NEW1=sine_table[11];
                  
                  if(TBL_POINTER_NEW1<TBL_POINTER_OLD)
                  {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                  TBL_POINTER_SHIFT = TBL_POINTER_NEW2 >> 11;
                  }
                    TBL_POINTER_NEW2=sine_table[22];
                      if(TBL_POINTER_NEW2<TBL_POINTER_OLD)
                  {
                  CCP1CON.P1M1=~CCP1CON.P1M1;
                  TBL_POINTER_OLD=0;
                   TBL_POINTER_SHIFT = TBL_POINTER_NEW2 >> 11;
                  }

                DUTY_CYCLE = TBL_POINTER_SHIFT;
                CCPR1L = sine_table[DUTY_CYCLE];
                TMR2IF_bit = 0;
               
                       }
                       
                       }
                  /*
                  PWM1_set_duty(sine_table[newduty]);
                  if(newduty=sine_table[newduty]+11)
                  {
                   PWM1_set_duty(sine_table[newduty]+11);
                  }
                  else
                  PWM1_set_duty(sine_table[newduty]+22);
                  INTCON.TMR2IF=0;
               }
               }    */

            
 void main()
 {
   TRISA=0XFF;
   TRISC=0XF0;
   TRISB=0XF8;
   CCP1CON=0X0C;
   PSTR1CON=0X1F;
   DUTY_CYCLE = 0;
   PR2=249;
   T2CON=4;
   T2CON.TMR2ON=1;
   T2CON.TMR2ON=1;
   TMR2IF_bit=0;
   while(TMR2IF_bit==0)
   {
   TMR2IF_bit=0;
   TMR2IE_bit=0;    //Enable Timer 2 Interrupr
   GIE_bit=1;     //Enable Global interrupt
   PEIE_bit=0;    //disable all peripheral interrupt
 //PWM1CON=    For dead time programming
 }
   PWM1_init(15000);      //Initialise PWM at 15KHZ
while(1){
    new_dc=0;   
       if(!(PORTA.B5)){
      debounce();
      if(new_dc<249)
      new_dc=new_dc+5;   //increment duty cycle
      }
       if(!PORTA.B4){
      debounce();
      if(new_dc!=0)
      new_dc=new_dc-5; //decrement duty cycle
           }
           if(newduty!=new_dc)
           {
           newduty=new_DC;
            PWM1_Start();
           //PWM1_set_duty(sine_table[newduty]) ;
            }
          }
        }
I have 240 values but constructing the positive half cycle (0-180degrees ) not 0-360 of a full cycle.
Please help.
 

Hi,

in my post#6 there are three pointers: pointerA, PointerB and pointerC.
--> Where can I find the corresponding three pointers in your code?

In my post#6 there is no sine table, but it seems you add some values from the sine table. Why?

****

If you now have 240 table entires for a half wave this means 480 steps for a 360 degree full wave.

If you want 120 degree (wich is a third from 360°) then you also need a third of 480 steps as offset.
480/3 = 160.
Where do you add those 160 and the corresponding

I expect something like
"pointerB = pointerA +160"
and
"pointerC = pointerA +320"

Klaus
 

Please could you convert what you are saying in codes,the theory I am understanding but coding is a concern.

Please !!
 

Hi,

isn´t this almost like your code?
"pointerB = pointerA +160"

this shoud give:

if pointerA = 0 then pointerB = 160.
if pointerA = 1 then pointerB = 161
and so on.

As simple as can be.

Klaus
 

OK, I've simplified it as much as I can. These are EXAMPLE numbers to keep the message short, use your real numbers of course:

const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

For phase1 first step uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase2 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase3 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

for the next step (second point of the sine wave)
phase1 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase2 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase3 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

for the next step (third point of the sine wave)
phase1 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase2 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase3 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

for the next step (fourth point of the sine wave)
phase1 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase2 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase3 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

for the next step (fifth point in the sine wave)
phase1 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase2 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};
phase3 uses const char table[12]={0,1,2,3,4,5,6,7,8,9,10,11};

the place in the table you pick all three values from is moved along one position each time and you wrap around to the beginning when you reach the end.

So you have one table of values and you pick three values out of it, one for each phase.
It starts with the value for phase1 from table[0], phase2 from table[4] and phase3 from table[8]. These would be the values to set the PWM ratios.
The next sine point would come from table[1], table[5] and table[9] respectively, each phase value taken from the next table location.
To make the program easier, instead of using fixed values for the table index, use a variable instead, lets call it 'i'.
If you start with the first sine step, make i=0, the PWM values become:
phase1 = table;
phase2 = table[i + 4];
phase3 = table[i + 8];

for the second and subsequent steps just add 1 to 'i'. You want it to wrap around to the beginning of the table again so when using 'i' exceeds the length of the table, set it back to zero. You can do it by comparing the value of 'i' or using modulo arithmetic based on the number of table entries.

Brian.
 

Dear FvM,here now I hope I created got and convenible values for sine wave generation,could you help me to handle the corresponding interrupts adapted to the PIC I am using PIC16F1936,It has 3ECCP (ECCP1,ECCP2 and ECCP3) and then has additional PWM modules CCP4 and CCP5,I hope by using the three ECCP Modules I can get the three signals required but remaining a great task of phase shifting which is has been explained here but what I want is the codes because I tried more than necessary and I failed.

See the values here for the sine table
Code:
123,
127,
129,
133,
135,
139,
141,
145,
146,
150,
152,
156,
158,
162,
164,
167,
169,
173,
174,
177,
179,
182,
184,
187,
189,
192,
194,
197,
198,
201,
203,
205,
207,
209,
210,
213,
214,
216,
218,
219,
221,
222,
223,
225,
226,
227,
228,
229,
230,
231,
231,
233,
233,
234,
234,
235,
235,
235,
236,
236,
236,
236,
236,
235,
235,
235,
234,
233,
233,
232,
231,
231,
230,
229,
228,
227,
226,
224,
223,
222,
221,
218,
218,
215,
214,
212,
210,
208,
207,
204,
203,
200,
198,
195,
194,
191,
189,
186,
184,
181,
179,
176,
174,
171,
169,
165,
164,
159,
158,
154,
152,
148,
146,
142,
141,
137,
135,
131,
129,
125,
123,
119,
117,
113,
111,
107,
105,
101,
100,
96,
94,
90,
88,
84,
82,
79,
77,
73,
72,
69,
67,
64,
62,
59,
57,
54,
52,
49,
48,
45,
43,
41,
39,
37,
36,
33,
32,
30,
28,
27,
25,
24,
23,
21,
20,
19,
18,
17,
16,
15,
15,
13,
13,
12,
12,
11,
11,
11,
10,
10,
10,
10,
10,
11,
11,
11,
12,
13,
13,
14,
15,
15,
16,
17,
18,
19,
20,
22,
23,
24,
25,
28,
28,
31,
32,
34,
36,
38,
39,
42,
43,
46,
48,
51,
52,
55,
57,
60,
62,
65,
67,
70,
72,
75,
77,
81,
82,
87,
88,
92,
94,
98,
100,
104,
105,
109,
111,
115,
117,
121,
123,
,Those values gives a complete cycle[0-360 degrees] and the values are divisible by 3 they are 240 values.

Please help,thanks
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top