Pages: [1] 2   Go Down
Author Topic: VFD Drive Program (Please criticise)  (Read 2389 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So I have been double busy trying to write program to control a three phase inverter

the middle leg is driven at 16kHz square and the other two legs each use an Arduino each


I use a reference table and an interrupt to cycle through at the calculated time according to an input voltage from a pot on A0

I use 0-2.5V relating to 25Hz-50Hz and the slower the speed the less the amplitude of the current, I also need to synchronise with the other arduino so that the two cycle through the table in a locked manner!

Code:
    #include <TimerOne.h>
             volatile boolean enable_my_ints;
             volatile boolean READY;
             volatile int TEST_VIN;
             volatile int TEST_VIN2;
             float TEST_HERTZ;
             float TEST_HERTZ2;
             float FLOAT_NUM;
             float FLOAT_NUM2;
             volatile int NUM;
             volatile int NUM2;
             volatile int HERTZ;
             volatile int HERTZ2;
             volatile int STEP_TIME;
             volatile int STEP_TIME2;
             volatile int Vin;
             volatile int count;


 int MainRef[] = {
 

  433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457,
  459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483,
  485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509,
  511, 
 
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537,
  539, 541, 543, 545, 547, 549, 551, 553, 555, 557, 559, 561, 563,
  565, 567, 569, 571, 573, 575, 577, 579, 581, 583, 585, 587, 589,
  591, 593

 
}; 
             volatile int index;
             volatile int increment ;
             long unsigned int REF = MainRef[index];
             int Iin;
             int ERR;
             int GATE = 12;
 
 
 
  void setup(){
 
             Serial.begin(9600);
             digitalWrite(6, HIGH);
             READY=false;
             pinMode(13, OUTPUT);
             pinMode(GATE, OUTPUT);
             pinMode(8, OUTPUT);
             pinMode(7, INPUT);
             pinMode(6, OUTPUT);
             bitClear(ADCSRA,ADPS0) ;
             bitClear(ADCSRA,ADPS1) ;
             bitSet(ADCSRA,ADPS2) ;
             
             
             float SETUP_VIN =(analogRead(A0)+ 494.0);
             float TEST_HERTZ = ((SETUP_VIN)/1020.0)*50.0;
             HERTZ =ceil(TEST_HERTZ);
             float FLOAT_NUM = HERTZ*1.6;
             NUM=ceil(FLOAT_NUM);
             
  TEST_VIN = SETUP_VIN;
 
 
 
  STEP_TIME = (1000000)/(HERTZ*2*NUM);
  index = 40;
  count = 0;
  increment=1;
  Timer1.initialize();
  Timer1.disablePwm(9);
  Timer1.disablePwm(10);
  digitalWrite(6, LOW);
 
  Serial.println(STEP_TIME);
  Serial.print("HERTZ  ");
  Serial.println(HERTZ);
  Serial.print("TEST_VIN  ");
  Serial.println(TEST_VIN);
  Serial.print("NUM  ");
  Serial.println(NUM);
  Serial.print("index  ");
  Serial.println(index);
  Serial.print("refindex  ");
  Serial.println(MainRef[index]);
  digitalWrite(6, LOW);
 
  while (digitalRead(7) == HIGH) {Serial.println("7 is HIGH...  ");
                                  if(digitalRead(7) == LOW){
                                  break;}
   
 
 
  }
 
  enable_my_ints= true;
  READY=true;
  Timer1.attachInterrupt(flash);
  Timer1.setPeriod(50000);
 
   
   
 
 
 






}
 void flash ()
 
{   
   if( enable_my_ints == true){
                               digitalWrite(13, HIGH);
                               
                               
   if (index<=40 -(NUM/2)){
       (increment=1);}
     
  else{if (index>=(40 + (NUM/2))){
    increment=-1;}
             
 }
   index = index+increment;
   
   count = count+1;
   
   if(count>= 20*NUM){
     noInterrupts();
     enable_my_ints =false;
     digitalWrite(6,HIGH);
     READY=false;
     digitalWrite(13, LOW);
     count=0;
     loop();}
 
   
   Iin=analogRead(A1);
   ERR = MainRef[index]-Iin;
   if (ERR>= 2){
     
   digitalWrite(GATE, HIGH);
 }

   else{
     if (ERR <= -2){
       
     digitalWrite(GATE, LOW);}
   }
       
   
digitalWrite(13, LOW);




}

}




 void loop(){
   Serial.println(MainRef[index]);
   
   
       while(READY==false){
                           
                           noInterrupts();
                           digitalWrite(13, HIGH);
                           enable_my_ints =false;
                   
                                         
if(digitalRead(7)==LOW){
                        digitalWrite(13,LOW);
                        digitalWrite(6,LOW);
                        enable_my_ints =true;
                        READY=true;
                        interrupts();
                        break;}
                       
     
}   
     
     
     
   
             Vin=(analogRead(A0)+494);
             volatile int x = abs(TEST_VIN - Vin);
     
if (x>15){ 
            delay(10);
            Vin=(analogRead(A0)+494);
            x = abs(TEST_VIN - Vin);
           
       
if(x>50){
           
            digitalWrite(6,HIGH);
            noInterrupts();
            enable_my_ints = false;
       
     
            volatile int SETUP_VIN2 =(analogRead(A0)+494);
            TEST_VIN2 = Vin;
            TEST_VIN = TEST_VIN2;
            Vin=analogRead(A0+520);
 
            float TEST_HERTZ2 = ((SETUP_VIN2)/1020.0)*50.0;
            float FLOAT_NUM2 = TEST_HERTZ2*1.6;
            NUM2=ceil(FLOAT_NUM2);
            HERTZ2 =ceil(TEST_HERTZ2);
            STEP_TIME2 = (1000000)/(HERTZ2*2*NUM2);
            index = 40;
            increment=1;
            count =0;
           
  Serial.print("x  ");
  Serial.println(x);
  Serial.print("NEWSTEP_TIME  ");
  Serial.println(STEP_TIME2);
  Serial.print("TEST_VIN  ");
  Serial.println(TEST_VIN);
    Serial.print("HERTZ2  ");
  Serial.println(HERTZ2);
  Serial.print("NUM2  ");
  Serial.println(NUM2);

 
 
 
 
  while (   digitalRead(7) == HIGH) {
           
  if(digitalRead(7) == LOW){
                            break;}
 

 
  }
 
  enable_my_ints= true;
  Timer1.setPeriod(STEP_TIME2);
  interrupts();
     
}
}   
     
   
 

}
       

The other program is virtually identical apart from array size and starting index etc


I am just looking for tips and ways I could improve the code thats all as tbh I have struggled with some parts of the program


Thanks in advance
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34243
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Why use three Arduinos? One could have done the job at only 16KHz. Then you would not have to worry about synchronising them.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am pretty new to programming and when I set out to do the easy part of generating a perfect square wave at 16 kHz I hit the problem of digitalwrite taking 4us which simply wasn't good enough the waveforms need to be pretty precise as if both transistors fire at the same time thenthe DC Bus will short out

So I use direct port addressing and the results is pretty good

For the other two legs I have a different lookup table and different step times which must be exact andI need to do analogue reads with a step time down to about 125us is quite a lot to ask from one arduino I reckon it could be done with two but my programming skills wouldnt allow for me to have two separate timed interrupts even if I knew how to set that up the problems must be much more complex

I am really keen to learn I would absolutely love to know if it would be possible to put this on one Arduino (not that it matters) if I had a faster board and more resources then of course one board is best but this is just a prototype with the idea of learning a few things


I want people to slate my program I am a complete novice and I really need the advice
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The maximum number of spaces between any two lines should be two or three, like


this.

Every time you use a brace (this { or this } ) put it on it's own line, and tab like this:
Code:
void loop()
{
  //See the single tab? ooh, pretty
  //I'm still tabbed in, let's do something
  digitalWrite(4, HIGH);
  dostuff();
  //Okay, that's enough looping
}

bool i;
void dostuff()
{
  if (i)
  {
    //Now we're double tabbed!
    int q = digitalRead(5);
    Serial.println(q);
  }
  else
  {
    Serial.println("failed");
  }
}

You can do all of that by going up to tools-> autoformat in the IDE.


Whenever you're testing something (in a while loop or if statement), it's false if the test is 0 and true otherwise. Thus, the line
Code:
while (digitalRead(7) == HIGH)
  can be changed to simply
Code:
while(digitalRead(7))
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 616
Posts: 49444
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
can be changed
But shouldn't be. The original meaning is MUCH clearer. What would happen in your code is the Arduino team decided that HIGH should be 0 and LOW 1?

Before you say that that will never happen, take a look at all the things changed between 22 and 1.0.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the tips

I have used the auto format thingy-ma-jig

I will leave the digitalRead(7)==HIGH as I can easily recognise it

Is there anything else people can criticise?, I was expecting a telling off for assigning certain variables globally, this is one of my biggest problems in deciding what needs to be global and what doesnt, it really baffles me when one part of the program doesnt see a variable elsewhere


Now my main challenge with my program is to sort out the speed change part


Code:
Vin=(analogRead(A0)+494);
             volatile int x = abs(TEST_VIN - Vin);
     
if (x>15){ 
            delay(10);
            Vin=(analogRead(A0)+494);
            x = abs(TEST_VIN - Vin);
           
       
if(x>50){
           
            digitalWrite(6,HIGH);
            noInterrupts();
            enable_my_ints = false;
       
     
            volatile int SETUP_VIN2 =(analogRead(A0)+494);
            TEST_VIN2 = Vin;
            TEST_VIN = TEST_VIN2;
            Vin=analogRead(A0+520);
 
            float TEST_HERTZ2 = ((SETUP_VIN2)/1020.0)*50.0;
            float FLOAT_NUM2 = TEST_HERTZ2*1.6;
            NUM2=ceil(FLOAT_NUM2);
            HERTZ2 =ceil(TEST_HERTZ2);
            STEP_TIME2 = (1000000)/(HERTZ2*2*NUM2);
            index = 40;
            increment=1;
            count =0;
           
  Serial.print("x  ");
  Serial.println(x);
  Serial.print("NEWSTEP_TIME  ");
  Serial.println(STEP_TIME2);
  Serial.print("TEST_VIN  ");
  Serial.println(TEST_VIN);
    Serial.print("HERTZ2  ");
  Serial.println(HERTZ2);
  Serial.print("NUM2  ");
  Serial.println(NUM2);

 
 
 
 
  while (   digitalRead(7) == HIGH) {
           
  if(digitalRead(7) == LOW){
                            break;}
 

 
  }


 
  enable_my_ints= true;
  Timer1.setPeriod(STEP_TIME2);
  interrupts();
     
}

I read Vin on A0 and subtract this value from the old Vin at SETUP if the difference is greater than 15 then I redo the test now as I am getting strange readings then I have had to change the retest and see if its changed by more than 50 before stopping the interrupts calculating the new step time and then waiting for the other arduino to send a low pulse onto pin7 to allow the two to break out together i.e if the other Arduino isnt ready yet then it will wait until it receives the low pulse

Now what I want to do is to stop the strange readings I am getting, if I knock the potentiometer it can read some weird values (it is a rather cheap one atm) I dont know how to go about changing it

What I plan on doing is reading the value from the pot with one Arduino and instead of reading the same value from the pot with the other Arduino I will write the reading so that both work with the identical value but I get strange readings (the single reading at setup always seems to work just fine?)


So I need to change the above code to maybe work out an average with a for loop but I don't know if thats a good idea

lets say the program is in the middle of the for loop, and itinterrupts but the count hits the limit and this is exeuted

 
Code:
if(count>= 20*NUM){
     noInterrupts();
     enable_my_ints =false;
     digitalWrite(6,HIGH);
     READY=false;
     digitalWrite(13, LOW);
     count=0;
     loop();}


The program will restart the loop and I am unsure of the consequences of leaving the for loop in the middle never to return, maybe it will just restart with no problems


So in a nut shell how can I stop weird readings from the pot and allow my speed to change only when x is more than 20 codes (about 1 Hz) without an obscure reading spoiling it all for me


Thanks in advance
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 15
Posts: 1330
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



 Here is a old thread about averaging readings. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293893508

You could also consider throwing out the highest and lowest readings before you create an average.
Logged


Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well I thought I would give a little update (I got a PM from an interested member)  I was successful in building a VFD, but due to uni health and safety I couldnt use 340VDC in the labs and I built a low voltage prototype which drove a dummy RL load at 30VDC

I actually won an award for my work as it was pretty impressive (to me at least!)

A pic of the proto type complete with electrical isolation, gate drive circuitry three phase inverter and current measurement stage

Speed select electronics which I had to implement a LP RC filter to filter the 16kHz transients from the common leg switching

One of the phase currents

and a shot of both outputs showing the 90 degree phase shift


* DSCF0525.JPG (2279.46 KB, 2832x2128 - viewed 62 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Upload limit oops

Speed selection with LP filter


* DSCF0526.JPG (2254.8 KB, 2832x2128 - viewed 14 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One of the currents

And both outputs check out the phase shift which is locked to the other through sync with two digi pins


* xxx.jpg (15.52 KB, 693x235 - viewed 3 times.)

* DSCF0616.JPG (2196.67 KB, 2832x2128 - viewed 5 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Output and pulse train check out the PWM!!!



* DSCF0603.JPG (2298.62 KB, 2832x2128 - viewed 12 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Again


* DSCF0604.JPG (2258.05 KB, 2832x2128 - viewed 13 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PWM close up


* DSCF0605.JPG (2305.63 KB, 2832x2128 - viewed 11 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Closer close up!


* DSCF0394.JPG (2292.68 KB, 2832x2128 - viewed 15 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 131
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I had to overcome loads of problems so many that the program was totally revamped to change interrupt times and due to the arduino uno bein g so slow (i needed to do lots in 80us)  i had to write an array of times (long story)

I still have lots of work to do before its up to a decent standard though so I will defo improve it

using 3 uno's is taking the pee a bit I would like to do it all on a single board and I want/would like a 32bit DSP and I have waited too long for the due now I think I will look further afield a get a proper micro controller as I have learned a fair bit about C++

Can anyone recommend me a good board to start with that is 32 bit with a faster processor say 80MHz ish? theres lots I need one with a 5v output preferably with plenty on the net to learn from
Logged

Pages: [1] 2   Go Up
Jump to: