Interrupts (really stuck)

I am trying to build a variable frequency drive

I will measure a current and compare to a reference value

my hall sensor gives 2.5V out for 0 Amps and has a range of 400mV acroos full load

So I write my look up table

 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 

 
}

Now I need to cycle through the table at dead set intervals which needs to be accurate in order to synthesise the sin wave (I know its a staircase!!!)

So I will use a timed interrupt and to calculate the time between table increments I will measure an input voltage between 2.5 and 5 Volts with that relating to 25 Hz-50Hz

Heres the snippet of code to calculate the step time, as the frequency increases then the amplitude of the sin needs to decrease also so less points in the table will be used i.e all 80 values for 50Hz but only 40 Values for 25 Hz this is what NUM is the number of values in the table

float SETUP_VIN =analogRead(A0);
  TEST_VIN = SETUP_VIN;

  float TEST_HERTZ = ((SETUP_VIN)/1023.0)*50.0;
  float FLOAT_NUM = TEST_HERTZ*1.6;
  NUM=ceil(FLOAT_NUM);
  HERTZ =ceil(TEST_HERTZ);
 
  STEP_TIME = (1000000)/(HERTZ*2*NUM);

So I have the step time calculated

I now add the step time to the timer so that I interrupt every step time to increment the table in a timed manner I start the table at index 40 (dead in the middle) and count up by NUM/2 and down the same

index = 40;
increment=1; 
Timer1.initialize();
  Timer1.disablePwm(9);
  Timer1.disablePwm(10);
  Timer1.attachInterrupt(flash);
  Timer1.setPeriod(STEP_TIME);

Heres the interrupt program

void flash ()
  
{  
    if (index<=40 + (NUM/2)){
    (increment=1);
  }
     
  else{
    if (index>=(40 - (NUM/2))){
    increment=-1;}
             
 }
   index = index+increment;
    
   Iin=analogRead(A1);
   ERR = MainRef[index]-Iin;
   if (ERR>= 2){ 
   digitalWrite(GATE, HIGH);}

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

}

Every time the period STEP_TIME passes the program jumps to flash where it increments or decrements the table and cycles through it measures the current and makes a decision on which transistor gate to turn on

Now this program so far works, I see with my scope that the interrupt does indeed work and the table does increment as I want it to

But.........................

I want to check the input voltage to see if any speed change has been commanded and this is where I am really stuck

What I want is to recheck the input voltage and see if its changed since it as setup, if theres a change then I need to stop the interrupt and recalculate the step time and then reload the timer with the new value

This is what I have done

 void loop(){
    Vin=analogRead(A0);
    int x = abs(TEST_VIN - Vin);

       
if (x>7){   
   
  
   
       
        Vin=analogRead(A0);
        x = (TEST_VIN - Vin);
       
     if(x>10, x<-10){
       
       digitalWrite(13, HIGH);
      noInterrupts();
      
  volatile int SETUP_VIN2 =analogRead(A0);
  
  TEST_VIN = SETUP_VIN2;
  Vin=analogRead(A0);
  float TEST_HERTZ2 = ((SETUP_VIN2)/1023.0)*50.0;
  float FLOAT_NUM2 = TEST_HERTZ2*1.6;
  NUM2=ceil(FLOAT_NUM2);
  HERTZ2 =ceil(TEST_HERTZ2);
 
  STEP_TIME2 = (1000000)/(HERTZ2*2*NUM2);
    Serial.print("NEWSTEP_TIME  ");
    Serial.println(STEP_TIME2);
    Serial.print("TEST_VIN  ");
    Serial.println(TEST_VIN);
    index = 43;
     increment=1; 
     delay(5000);
     Timer1.setPeriod(STEP_TIME2);
     interrupts();
     digitalWrite(13, LOW);

        
  
  
        
        
}
}   
    
      }

Vin is re-read

TEST_VIN-Vin is calculated and x = abs(TEST_VIN - Vin) is used to see how much the value has changed

Because of some dodgy readings I have done a double if to try to (unsuccesfully) stop strange readings

if the voltage has changed by more than 10 codes I want to re setup the step time but I want to stop the interrupt why it does this hence me trying to delay it and writing pin 13 high so I can see it on my scope

But it just does not work right I think it may well have something to do with me reusing values all over the place I just dont know what to do to move this forward I have been on 3 days trying

Here is my entire program

#include <TimerOne.h>
 
  volatile int TEST_VIN;
  volatile int TEST_VIN2;
  float TEST_HERTZ;
  float FLOAT_NUM;
  float TEST_HERTZ2;
  float FLOAT_NUM2;
  volatile int NUM;
  volatile int HERTZ;
  volatile int STEP_TIME;
  volatile int NUM2;
  volatile int HERTZ2;
  volatile int STEP_TIME2;
  volatile int Vin; 
  volatile int x;


 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;
  int SPEED_CHANGE;
  
  
  void setup()
{ 
  
  Serial.begin(9600);
  
   pinMode(13, OUTPUT);
   pinMode(GATE, OUTPUT);
   pinMode(8, OUTPUT);
   pinMode(7, INPUT);
  
  bitClear(ADCSRA,ADPS0) ;
  bitClear(ADCSRA,ADPS1) ;
  bitSet(ADCSRA,ADPS2) ;
  
  index = 40;

  float SETUP_VIN =analogRead(A0);
  TEST_VIN = SETUP_VIN;

  float TEST_HERTZ = ((SETUP_VIN)/1023.0)*50.0;
  float FLOAT_NUM = TEST_HERTZ*1.6;
  NUM=ceil(FLOAT_NUM);
  HERTZ =ceil(TEST_HERTZ);
 
  STEP_TIME = (1000000)/(HERTZ*2*NUM);
  Serial.println(STEP_TIME);
  Serial.print("HERTZ  ");
  Serial.println(HERTZ);
  Serial.print("NUM  ");
  Serial.println(NUM);
  Timer1.initialize();
  Timer1.disablePwm(9);
  Timer1.disablePwm(10);
  Timer1.attachInterrupt(flash);
  Timer1.setPeriod(STEP_TIME);
 
    
    
  
  increment=1; 
  

}




 void flash ()
  
{    digitalWrite(8, HIGH);
    if (index<=40 + (NUM/2)){
    (increment=1);
  }
     
  else{
    if (index>=(40 - (NUM/2))){
    increment=-1;}
             
 }
   index = index+increment;
    
   Iin=analogRead(A1);
   ERR = MainRef[index]-Iin;
   if (ERR>= 2){ 
   digitalWrite(GATE, HIGH);}

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


 void loop(){
    Vin=analogRead(A0);
    int x = abs(TEST_VIN - Vin);

       
if (x>7){   
   
  
   
       
        Vin=analogRead(A0);
        x = (TEST_VIN - Vin);
       
     if(x>10, x<-10){
       
       digitalWrite(13, HIGH);
      noInterrupts();
      
  volatile int SETUP_VIN2 =analogRead(A0);
  
  TEST_VIN = SETUP_VIN2;
  Vin=analogRead(A0);
  float TEST_HERTZ2 = ((SETUP_VIN2)/1023.0)*50.0;
  float FLOAT_NUM2 = TEST_HERTZ2*1.6;
  NUM2=ceil(FLOAT_NUM2);
  HERTZ2 =ceil(TEST_HERTZ2);
 
  STEP_TIME2 = (1000000)/(HERTZ2*2*NUM2);
    Serial.print("NEWSTEP_TIME  ");
    Serial.println(STEP_TIME2);
    Serial.print("TEST_VIN  ");
    Serial.println(TEST_VIN);
    index = 43;
     increment=1; 
     delay(5000);
     Timer1.setPeriod(STEP_TIME2);
     interrupts();
     digitalWrite(13, LOW);

        
  
  
        
        
}
}   
    
      }

The digital writes and serial stuff can all be dropped later its only for me to try and see whats going wrong

Any help much appreciated, can I use the nointerrupt() to stop the timer command or should I detach interrupt? it doesnt seem to work either way so how would an expert here go about resetting up something I did earlier its really confusing how the program doesnt see things from the setup within the loop

I'm confused, you seem to be both measuring an external waveform and synthesising a waveform too? Your lookup table is linear, is it going to be a sine wave in the future? Have you heard of DDS (direct digital synthesis) ?

I am measuring a current, which is a hall sensor and its voltage is 2.5 for 0 Amps hence a digital read is 512 at 0 A at full load peak (0.34 A)I measure 593 and at minimum (-0.34 A) I measure 433

So thats the measurements

What I am doing is turning on an IGBT and measuring the current and by measuring fast enough I cam turn on and turn off a transistor depending on how much current is flowing so I need a current reference so i can compare my measurement to and decide to turn on or off

So the look up table represents the values I want my measurement to be and by cycling through the table at the right time step will approximate the sine wave I want

Now I do realise the wave is a staircase wave and its not a true sine but all the literature I have read has the same staircase waveform

I have heard of DDS before but its not something I am familiar with but do I need it?, my program works as it should in the setup, its only when the speed changes that I have problems I think its because I am repeating the same thing as above and some value isnt updating? it confuses me where to define ints etc as sometimes different parts of the program dont see them unless i put them global

if I declare Vin=analogRead(A0);

and then below I do something with Vin

say

x=Vin/2

will that re-read A0 or just use the old reading?

My problem I think boils down to stopping the interrupt

Why cant I do

digitalWrite(13, HIGH);
NoInterrupts()
delay(500);
Timer1.set.Period(TIME);
digitalWrite(13,LOW;

and make it stop interrupting I am open to any advice in laying out the program or whatever anyone might be able to ofer

In that example Vin is a variable, the analogRead only happens once when you call analogRead - accessing the Vin variable just looks at the current value stored there.

As for blocking interrupts, don't do that for long periods (certainly not 500ms!). The easiest way to control an interrupt routine is to use a volatile variable that the interrupt routine looks at to determine if it should do any more work - something like:

  volatile boolean enable_my_ints = true ;

In the interrupt routine just test this first. Anywhere in the rest of the code you can set it to false to inhibit the routine for a while without blocking any other interrupts like the timer ones.

but if I do

volatile int Vin = analogRead(A0);

.........
...........
...............
.............

x = Vin/2

Will that re-read A0 or still just use the Vin it read earlier

How do I get it to read again instead of typing analogRead

I dont understand what you mean with

volatile boolean enable_my_ints = true ;

I dont get how that would delay????

Now I dont actually need to block the interrupt I just want to be able tosee a big pulse on my scope while the interrupt pulse stops! 500ms is taking the pee! but surely if I stopped the interrupt this should be ok I know I cant use delays in the interrupt a 500us delay would be enough

whats wrong with

void setup(){
Timer1.initialize()
Timer1.attachinterrupt(ERIC)
Timer1.setPeriod(time)
}

void loop(){

..........
..........
..........

NoInterrupts()
........
........
.......
Timer1.setPeriod(time)
Interrupts()
}

Or should I use the dettach interrupts command and then re attach???

Any help is much appreciated

This part seems to work lets see if i can talk through what I think happens

void setup()
{

Serial.begin(9600);
//Set up outputs/inputs

pinMode(13, OUTPUT);
pinMode(GATE, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, INPUT);

//Change the ADC prescale values to speed up analog read

bitClear(ADCSRA,ADPS0) ;
bitClear(ADCSRA,ADPS1) ;
bitSet(ADCSRA,ADPS2) ;

//Start in the middle of my lookup table = 2.5V = 0 A
index = 40;

//Read A0 which is the voltage from a pot divider 2.5V to 5 Volts read in 512-1023
float SETUP_VIN =analogRead(A0);

//used later
TEST_VIN = SETUP_VIN;

//change the 512 to 1023 reading to a corresponding Hz command (need float to do (512...1023)/1023 couldn't get it to work with (512...1023)*50/1023????)

float TEST_HERTZ = ((SETUP_VIN)/1023.0)*50.0;

//Number of values in my lookup table to use 80 values max at 50 Hz 40 Values at 25 Hz
the 1.6 is from(TEST_HERTZ/50)80=TEST_HERTZ1.6;

float FLOAT_NUM = TEST_HERTZ*1.6;

//Round the floating values up
NUM=ceil(FLOAT_NUM);
HERTZ =ceil(TEST_HERTZ);

//Calc the step time in us the total number of values in my table is from the minimum to max only I start in middle of table and count up to the max then down to min and then back to zero step time is given by T/(4*(NUM/2) so

STEP_TIME = (1000000)/(HERTZ2NUM);

//I initialize timer disable PWM attach the function to call at interrupt (flash)and then set period to steptime and it certainly does work

Timer1.initialize();
Timer1.disablePwm(9);
Timer1.disablePwm(10);
Timer1.attachInterrupt(flash);
Timer1.setPeriod(STEP_TIME);

}

So it works and I can see the pulse I setup everytimer interval and if I change the voltage and reset the time period between interrupts changes!!

So now I want to monitor the input voltage on A0 and see if its changed by a decent amount if it has I want to stop the interrupt why I do the setup stage again

so

my loop

void loop(){

//Check Vin again does this actually use the old Vin I measured at setup? do I need a new variable?
Vin=analogRead(A0);

//TEST_VIN should be the Vin at setup if it didntchange then the difference will be zero use abs to get rid of negative x should be the difference between the setup and the new

int x = abs(TEST_VIN - Vin);

//if the pot has been turned then Ineed to do stuff
if (x>7){

Vin=analogRead(A0); //is this again the old Vin????

x = (TEST_VIN - Vin); // is this line compatring the same stuff as before??

//I recheck as there seems to be some strange readings from time to time maybe linked to messing with the ADC values??

if(x>10, x<-10){

digitalWrite(13, HIGH); //set pulse to see on scope

//I need to stop interrupt I have no faith in nointerrupt command it just isnt working what can I use here?
noInterrupts();

//I now do the same as in setup but I have tried new variables with a 2 on the end

volatile int SETUP_VIN2 =analogRead(A0);

TEST_VIN = SETUP_VIN2;
Vin=analogRead(A0);
float TEST_HERTZ2 = ((SETUP_VIN2)/1023.0)50.0;
float FLOAT_NUM2 = TEST_HERTZ2
1.6;
NUM2=ceil(FLOAT_NUM2);
HERTZ2 =ceil(TEST_HERTZ2);

STEP_TIME2 = (1000000)/(HERTZ22NUM2);

index = 40;

//reset the timer and reattach interrupts
Timer1.setPeriod(STEP_TIME2);
interrupts();
digitalWrite(13, LOW);

}
}

}

I hope that makes sense

I've recently had fun getting Timer1 to work for me. After much mucking about and reading of code I came up with the following way to get it to work.
In setup(), initialize it using only these two statements:

  //initialize calls setPeriod so do it all in one.
  Timer1.initialize(STEP_TIME);
  // this also starts the timer
  Timer1.attachInterrupt(flash);

To stop the timer use:

  Timer1.stop();

To start it going again:

  Timer1.resume();

Pete