Timer (advice needed)

I posted this topic

http://arduino.cc/forum/index.php/topic,81805.0.html

My question is if I set up a timer in a program to increment a look up table and after the timer count the program branches to a subroutine (or just goes elsewhere) to increment the table and perform some actions

The question is will the timer still continue to count even while in the subroutine

For example

I set a timer to 5 seconds

after 5 seconds the program branches to a routine/interrupt lets say it takes 2 seconds to execute the interrupt am I right in thinking that the timer will only count up a further 3 seconds until the next interrupt?

i.e the 2 seconds for the interrupt is still counted within the 5 second count and I only need worry that the interrupt takes less time than my count

Am I right???

My question is if I set up a timer in a program

There are some libraries that let you set timers, and get called back when the timer goes off. Are you using one of them to set up your timer? If so, which one?

I set a timer to 5 seconds

after 5 seconds the program branches to a routine/interrupt lets say it takes 2 seconds to execute the interrupt am I right in thinking that the timer will only count up a further 3 seconds until the next interrupt?

This is true. If you want different behavior, in the timer callback, you stop the timer, do whatever you need to do, and, at the very end, set the timer for another 5 seconds.

Many thanks for your reply

The fact that the timer will continue to count is good news to me my problem now becomes making my code work fast enough!

I have written some code but TBH I am embarrassed to post it :), I need the Arduino to do quite a bit in a pretty short time

I have a lookup table

int MainRef[] = {515, 516, 517, 518, 519, 520, 521, 522, 
523, 524,525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 
536, 537, 538, 539, 540, 545, 546, 547, 548, 549, 550, 551, 552, 
553, 554,555, 556, 557, 558, 557, 556, 555, 554, 553, 552, 551,
 550, 549,548, 547, 546, 545, 544, 543, 542, 541, 540, 539, 538, 
537, 536,535, 534, 533, 532, 531, 530, 529, 528, 527, 526, 525, 
524, 523,522, 521, 520, 519, 518, 517, 516, 

515, 514, 513, 512, 511,510, 509, 508, 507, 506, 505, 504, 503, 
502, 501, 500, 499, 498, 497,496, 495, 494, 493, 492, 491, 490, 
489, 488, 487, 486, 485,484,483, 482, 481, 480, 479, 378, 477, 
476, 475, 474, 473, 472,471,472, 473, 474, 475, 476, 477, 478, 
479, 480, 481, 482, 483, 484, 485, 486, 487, 489, 490, 491, 492, 
493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 
506, 507, 508, 509, 510, 511,512, 513, 514, 515
}

Now the look up table needs to increment at a certain rate set by a potentiometer 2.5-5 Volts and to complicate matters slightly it also needs to decrease amplitude for slower frequencies (V/Hz principle)so the number of elements in the array decreases as the step-time increases hence some rules to max and min values need to be setup

The thing is my programming isnt too hot! and I need the arduino to be pretty fast for the 44 element array above to describe a 50 Hz sin then thats a step size of about 116us, I know I could decrease the values in the table but the 116us is just right and it lines up exactly with my sensor! but I would like to just get it working and see just what speed is achievable

So in a nutshell what I need to do is

Setup the variables and constants first

I have the number of elements in the array constant 172 I have Vin from pot and a current measurement Iin

I have digital pins 8 and 9 as outputs

read input from pot (fast!) 2.5V-5V Lets call it Vin on A0 (reading 512-1023)

(Vin/1023)*50 = commanded frequency
(Vin/1023)*17 = the number of elements required in array to decrease the sin magnitude as the frequency decreases lets call it imax

Step time Ts = (1/f)/(imax-1)

Timer counts for Ts then increments table lets call current value REF (up to maximum imax then back down then the same but negative)

Read Hall sensor input lets say Iin on A1

Ref-A1 = error
if (analogValue > threshold) {
digitalWrite(ledPin, HIGH);
if(ERR>1) {
//Pin 8 Low and Pin 9 High

}
if(ERR<-1){
\Pin 8 high and Pin 9 Low

}

Then go back to the timer and start again it would be good to be able to check whether the pot voltage has changed by a certain percent but I think I have enough to learn

I know I can use direct port addressing I had to do that to create a 16 kHzsquare wave with dead time

void setup()
{ 
  DDRB = DDRB | B110000;} // Set digital pins 12 and 13 to outputs

void loop()
{  
  
    
  PORTB = B100000;         // Digital pin 13 high
   delayMicroseconds(30);  //30 microsecond delay
   PORTB = B000000;        // Digital pin 13 low 
   delayMicroseconds(2);   //2 microsecond delay
   PORTB = B010000;        // Digital pin 12 high
    delayMicroseconds(30); //30 microsecond delay
   PORTB = B000000;        // Digital pin 12 low
   delayMicroseconds(2);    //2 microsecond delay
   
}

I have monitored the output with my scope and its really good what I really need to know is how to do an analog read quickly but is there many members here who can advise on using direct port addressing?

I am working on my code setup part I will upload it in a while I would really really appreciate it if anyone can advise me

delayMicroseconds(2); //2 microsecond delay

The Reference page says delayMicrosecond is only good for 3uS & up.

"This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times."

Might need to find a different way to kill a little time, like a little while loop that just counts increments a counter a few times. 2 uS is 32 clock cycles.

I have read that before but it works really well when direct accessing I have some PC scope shots actually

The ELVIS isnt the best I have manually measured them with my digital scope and it takes approx 62ns per instruction

Please dont laugh at my code it isnt even near to complete

I need to know how to read fast I have the arduino cookbook and I have seen the ADCSRA,ADPSo stuff but I really dont understand it

HELP!!!

int MainRef[172] = {
515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 
528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 
541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 
554, 555, 556, 557, 558, 

557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, 545, 
544, 543, 542, 541, 540, 539, 538, 537, 536, 535, 534, 533, 532,
531, 530, 529, 528, 527, 526, 525, 524, 523, 522, 521, 520, 519,
518, 517, 516, 515, 

514, 513, 512, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 
501, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 489, 
488, 487, 486, 485, 484, 483, 482, 481, 480, 479, 378, 477, 476, 
475, 474, 473, 472,  

473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 
486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 
499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 
512, 513, 514
}


void setup()
{
  DDRB = DDRB | B000011;
  int Vin = 2;
  int Ref = MainRef [index];
  long int time
  volatile long int num;
  volatile long int steptime;  
  i=0;
  long int dial = analogRead(Vin); 
  long int num = (dial/1023)*172;
  long int freq = (dial/1023)*50;
  long int steptime = (1/freq)/(num-1);
}
 void loop()
 Timer count for (steptime)??????????? HOW
 
 for( int index =0; index< num/4; index++){
 I want to increment table positive}
 
 \\ when the table reaches maximum I want to decrement back to zero
 for( int index = num/4; index--){
   I want to decrement the table back to zero}
   
   
   
   
 
 
 Read A1
 
 int ERR = Ref-A1
 
 if(ERR>1;){
   
 PORTB = B000010;
 }
 
 if(ERR<-1){
   
 PORTB = B000001;
 }

Can anyone please help?

Or even advise me what I need to do to get help I have really tried and have hit a brick wall

I don't really understand what it is you're doing.

Hi Resinator Your request is over the ability of Arduino's language (library). But if you use the Arduino as AVR one chip uC board, then your request is not so difficult. I think so. You had better timer directly and use timer interruput. To do so, you learn about AVR uC. You can get many manuals from Atmel web site. and AD converter results are affected by noise. Please be carful.

Sorry I'm poor in English.

Nabe

Thanks for the replies

Crossroads I am trying to develop a variable frequency drive for an AC motor, I did a topic in the power and motors section theres a link in my first post

in a nutshell I use three arduinos to drive a three phase inverter (6 IGBT’s or 6 MOSFETS)

One arduino will drive the middle leg with a 16 kHz square wave with 2us dead time between switchings to prevent shorting the DC bus, I have used direct port accessing and the program does its job really well

the other two Arduinos will do the same job only with a phase shift

The job is to cycle through a look up table at a calculated rate which will synthesise a sine wave I will use a Hall current sensor to measure the instant current and the difference between the table and the measurement is the error, if the error is positive not enough current is flowing and the top switch needs to be turned on and vice versa for a negative error

So I write my lookup table lets make this easier

int REF = {5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4,}

So I have 20 elements in the table which will be 19 steps for a whole cycle if we wanted a 50Hz output the the steptime (time between incrementing the array) = 0.02/19

Steptime TS = 1052us (ish)

So I need to setup a timer which might/will branch to an interupt and the program needs to

  1. read the Hall sensor(which a 10 bit binary number ranging from 471 to 568 IIRC!)
  2. Current ref value - measured value = error
  3. if error positive turn on top and turn off bottom vice versa for negative error
  4. get back to timer before next count!!!

The absolute maximum speed the table will increment is about 116us so I need to do 1-4 in 116us

I do have some knowledge of programming but I struggle piecing everything together let me try

I need to include the timer library #include<MsTimer2.h>

I need to direct port access digital pins lets say 8 and nine DDRB = DDRB | B000011;

I need to analog read fast so I can adjust the prescale value (I dont understand this) but will this speed up the process?

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

i am led to believe this sets the ADC prescale to 16 but where the hell 16 comes from I dont understand!

#include<MsTimer2.h>// Timer Library

  DDRB = DDRB | B000011;

int REF[] = {5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4,};

void setup()
{ long int index = 0;
  int Vin = 0;
  int Iin = 1;
  long int dial = analogRead(Vin); 
  long int num = (dial/1023)*172;
  long int freq = (dial/1023)*50;
  long int steptime = (1/freq)/(num-1);
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);

}

void loop(){
  MsTimer2::set(TS, INTERRUPT);
  MsTimer2::start();

for(index =0, index< num; index++)


void INTERRUPT(){
int MEAS= analogRead(Iin)
int ERR = Ref[index] - MEAS

if(ERR>1){
PORTB = B000010;}

if(ERR<-1){
PORTB = B000001;
}

Thats about as far as I can go I would like people to pull my code apart and heavily criticise it as much as possible, I know it isnt finished but I am stuck now

I'm not following what you're trying to do, but the array you're working with looks like a straight forward sawtooth pattern. Is this the 'sin wave' you refer to? It doesn't look remotely sin-wavy to me. What's this about 'incrementing the table' and 'turn on top and turn off bottom vice versa' etc?

If you're trying to synthesise a 'sin wave' (or saw tooth, or whatever) how fussy are you about quantisation errors in the shape of the wave? I mean, if you're only driving a motor it would probably not care whether you give it a sin wave or a square wave. In other words, is your journey really necessary? And if you do need to output a wave, how have you determined how accurately you need to control the shape of it, and how many distinct output steps you need to achieve that?

One final comment about your algorithm - if you have 20 values that you are going to cycle through, it seems to me that's 20 steps not 19. The difference could be significant when you're working out tight timing constraints.

Hi Peter, what I am trying to do is IMO very interesting it takes quite some explaining!

I basically set out to develop a variable frequency drive for an AC motor (single phase), I work in power and its something I have always found interesting programming isn’t my strongest point but I know space vector modulation probably isn’t possible with an Arduino! which is why I have settled for an hysteresis current controller, the motor has two windings main and aux and it will be connected to the three phase inverter as in the attached pic (Its an unbalanced three phase load!!)

I build a rectifier to give a DC bus and the Arduino is used to drive the transistors via opto isolated gate drives

You can think of each winding connected to a half bridge inverter each leg is two transistors in series this is the top and bottom!) the middle leg is common and switched at a constant 16 kHz square to give a reference of VDC/2,

So with each winding connected to a half bridge inverter (and a VDC/2) if the top transistor of the bridge is turned on then the current will pass through in the positive direction into the middle leg

if the bottom transistor of the bridge is turned on (Top must be off) then current will flow in the negative direction (every time 16 kHz is high)

The top and bottom can never be on or the DC bus will short hence dead time, some gate drives have in built dead time and this is probably what I will do as the drive will be more easily tuned

The hysteresis current control uses a sensor (Hall effect current transducer) to measure the current and it takes 5V DC supply its output is 2.5V at 0A and 5 V at +full scale (not to be used at full scale) for my sensor and my full load current the output is approx 2.5V +/-200mV

Hence an analogue read returns ~512 for 0 amps and as the amps go up the value of the analogue read goes up at positive peak I read 558 and negative peak I read 472 the look up table is developed to match what I get from the hall sensor

Heres a code I copied which I set up to map the value to -400mA to 400mA and it reads the current and prints the reading from my hall sensor

const int analogInPin = A0;  
const int analogOutPin = 9; 
int sensorValue = 0;        
int outputValue = 0;        

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);            
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 464, 565, -400, 400);  
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);          

  // print the results to the serial monitor:
  Serial.print("sensor = " );                      
  Serial.print(sensorValue);      
  Serial.print("\t output = ");      
  Serial.println(outputValue);  

  delay(1000);

I need to compare this reading to a reference table but its very slow obviously I need to totally rewrite the code drop the serial print and mapping etc and implement it in my program

I used the program to determine the reference values as the heart of the control is that the current in the aux winding needs to be 90 degrees leading the current in the main winding so a reference table what I need the current to be will be cycled through in the required time and after each time step I read the actual current if I subtract the actual current from the reference I want this gives the error so I want 10 Amps I read 8 Amps 10-8 = 2 Amp error the current I actual have isn’t enough (error is positive) and I need to turn on the top transistor to give more positive current

If I had too much actual current then error is negative and I need negative current so the bottom transitor needs to be on, IMO this is a fantastic project, due to the high voltages I appreciate that its not for most people as special equipment and precautions are needed

I have been told to use pointers and direct addressing (I have to find the direct addresses of the analog pins to do a read which I can’t find anything to fill me with confidence!) in order to do an analog read but whats the difference to that and changing the prescale value I really dont know

so to summarise

Two windings and the current in the aux needs to lead the current in the main

Three legs to the inverter with the middle leg common to both windings switched at 16 kHz (with deadtime)

Three Arduinos one for each leg with two doing the same job but with different reference values

The job

Measure input from pot to determine output speed (range 2.5 to 5 Volts corresponds to 25 to 50Hz)

Set up table and increment at the required speed to synthesise sine wave as it looks from the sensor

After each increment the measurement is taken and subtracted from the reference

Decision is made on which transistor is to switch on and then the program needs to wait until the next count then increment and keep on going

The extra bells and whistles is to check if pot has changed by a certain percent and to synchronise with the other arduino by having a bit check or whatever wait for the rounding error (et al!) time

I hope that explains it, please if its unclear let me know even if you can’t help maybe somebody else who can also can’t understand, like I say programming isn’t my strong point I like maths and I think in maths but I know the binary numbers adding and subtracting dont give me the positive and negative errors I think in so mods are needed everywhere

Can anyone please help no matter how small, the direct addresses of analog pins would be good I need to point to them somehow =(

PS

I thought (I am often wrong!)

If there was 20 values in the table I would start at the first element already

int index =0;

So 19 steps later I am at the last element and we complete the circle by stepping from the last element to the start again!, 20 steps to get to where we started (n-1) steps to get to end of the list we miss the last value in the table as its the same as the first

Any takers?