void loop cannot execute and returns values on Arduino Mega 2560

Slumpert:

sample_time = 10;        //Loop for sample duration of sec

//  Loop for sample duration of 10 sec
  while((millis() - startTime) < sample_time)
  {




The fact that your “sample time” is actually only .01 seconds might be a issue.

Yes, but if I increase the sample time the respond times dramatically decreases and PWM is not working.

While loops block, you should not have any, let loop() be the only loop....

MarkT:
While loops block, you should not have any, let loop() be the only loop....

No diffrence. Commenting while loop did not help!

I don’t even know what code your talking about anymore.

Much less what the actual project is, or how it’s wired, or what platform it’s running on.

Your last update post, did it include the actual code your still having a problem with?

Yes, perhaps repost the code as it is now and a description of what it is doing and a description of what you
want it to be doing. This will be easier to figure out.

MarkT:
Yes, perhaps repost the code as it is now and a description of what it is doing and a description of what you
want it to be doing. This will be easier to figure out.

I did many many changes on several source codes but all of them was unsuccessful except YOUR code Mark. So I tried to mix your PWM code with my tachometer code and seems it is working now, so many thanks! The final code is as follows:

// For the UNO et al.
#define PERIOD 250   // 250 cycles = 15.625us for each half of waveform, 32kHz
#define HALF 125     // half the period is the default PWM threshold - gives square wave.
#define MAXAMP 31



void setup_timers ()
{
  TCCR1A = 0xF2 ;  // phase correct (mode 1010, ICR1 controls period)
  TCCR1B = 0x11 ;  // prescale by 1, change to 0x12 for prescale by 8
  TIMSK1 = 0x01 ;  // overflow interrupt
  TCCR2A = 0x31 ;  // phase correct (mode 101, OCR2A controls period)
  TCCR2B = 0x09 ; // prescale by 1, change to 0x0A for prescale by 8
 
  ICR1  = PERIOD ;    // 31.25us cycle time, 32kHz PWM but 64kHz drive pulses (differential)
  OCR2A = PERIOD ;
 
  OCR1A = HALF-100 ;    // example U drive
  OCR1B = HALF ;
  OCR2B = HALF+100 ;    // example W drive
 
  GTCCR = 0x83 ; // clear and halt prescalers
  TCNT1 = 0xFFFF ;  // synchronize counters exactly.
  TCNT2 = 0 ;
  GTCCR = 0x00 ; // allow prescalers to fly
}


void setup ()
{
  Serial.begin(57600);
  setup_cosines () ;
  setup_timers () ;

  pinMode (9, OUTPUT) ; // OC1A pin = U drive
  pinMode (12, OUTPUT) ; // OC1B pin = V drive
  pinMode (11, OUTPUT) ; // OC2B pin = W drive
  pinMode (0, INPUT) ; // pot pin
  pinMode(A7, OUTPUT); //LED out pin
  pinMode(A5,OUTPUT); //Sensor VCC pin
  pinMode(A3,INPUT); //Sensor Input pin
}

volatile byte u = HALF ;
volatile byte v = HALF ;
volatile byte w = HALF ;


ISR (TIMER1_OVF_vect)   // overflow triggers at BOTTOM, update all the compare regs, which are sampled at TOP
{
  OCR1A = u ;
  OCR1B = v ;
  OCR2B = w ;
}

#define  DEG_360  0x200
#define  DEG_120  0x0AB

char cosine_tab [DEG_360+1] ;  // fails to work if less than 0x202.

void setup_cosines ()
{
  for (int i = 0 ; i < 0x202 ; i++)
  {
    float a = i * 6.283185 / 0x200 ;
    if (i <= DEG_360)
      cosine_tab [i] = round (127.0 * cos (a)) ;
  }
}

/////////////////////////////////////////////////
unsigned int phase = 0 ;
int freq ;        ////0
int amplitude = MAXAMP ;
/////////////////////////////////////////////////
long startTime = 0;
int state, prevState = 0;
int sensor = 0;
long counter = 0;
double Ff = 0;
long sample_time;
int magnet_number;       
int sensore_output_voltage = 1000;
int prim_rpm = 0;
long sec_rpm = 0;
float  pot_co = 0;
/////////////////////////////////////////////////

int my_cosine (int ph)
{
  ph &= DEG_360-1 ;
  int res = cosine_tab [ph] ;
  res *= amplitude ;
  return (res + 0x0F) >> 5 ;
}

void loop ()
{

sensor = 0;
  Ff = 0;
  state = 0;
  prevState = 0;
  counter = 0;
  startTime = millis();
  sample_time = 5000;                                  //5000 for 5 sec Loop for sample duration of sec
  magnet_number = 1;                                   //is number of magnets per revulotion
//  rpm = 0;
//  samp=0;
  
  //enable sensor and turn on LED when touched.
  digitalWrite(A5, HIGH);

  //Loop for sample duration of 10 sec
  while((millis() - startTime) < sample_time)
  {
    sensor =  analogRead(A3);

    if (sensor > sensore_output_voltage)  //sensore output voltage
    {
    state = 1;
           
    }
    else
    state = 0;
     digitalWrite(A7,state); // Blinking LED when sensor Activated

    //On change of state increment counter.
    //A change in state twice represents one revolution
    if(state != prevState)
    {
      counter++;
      prevState = state;
     
    }

//    freq = map(analogRead(A0),0,1023,0,100);
    pot_co = map(analogRead(A0),0,1023,2500,50);
    pot_co = pot_co / 50.0;
    sec_rpm = prim_rpm / pot_co;
    freq = map(sec_rpm, 10, 1500, 0, 100);
    
  phase += freq ;
  
  int newu = my_cosine (phase) ;
  int newv = my_cosine (phase - DEG_120) ;
  int neww = - newu - newv ;
  newu += HALF ;
  newv += HALF ;
  neww += HALF ;
  u = newu ;  // no masking of interrupts needed as u,v,w variables are single byte each.
  v = newv ;
  w = neww ;

  delayMicroseconds (2600) ;      
  
  }
   digitalWrite(A7,LOW);
  digitalWrite(A5, LOW);
  
  counter = counter / 2; 

   
  prim_rpm = counter / magnet_number * 50;
}

The idea of this code is that tachometer will read speed of a shaft (not coupled to the motor) and force the motor to rotate with the speed of 0 to 100% (using pot on pin A0) of the shaft speed using PWM.

So, now I have 3 question:

1- For such speed control using above code, do I need PI control to add to the above code or not? (there is not any speed feedback from motor, we only have speed of a shaft which is not mechanically coupled with motor).

2- Mark set the Microseconds delay to 1000, I set it to 2600 to get approximately 50 Hz, how to accurately calculate the delay for 50Hz?

3- To drive 6-pulse IGBT, I want to use three IR2110 drivers, but as I found in its datasheet I need a H and L input for each phase to fire H and L output from the driver for each IGBT pairs. But on the code output I only have three output for 3 phase. So how to produce H and L signal for each phase?

Many thanks for your helps.

Any idea?

Maslord:
I did many many changes on several source codes but all of them was unsuccessful except YOUR code Mark. So I tried to mix your PWM code with my tachometer code and seems it is working now, so many thanks!

....

The idea of this code is that tachometer will read speed of a shaft (not coupled to the motor) and force the motor to rotate with the speed of 0 to 100% (using pot on pin A0) of the shaft speed using PWM.

So, now I have 3 question:

1- For such speed control using above code, do I need PI control to add to the above code or not? (there is not any speed feedback from motor, we only have speed of a shaft which is not mechanically coupled with motor).

Without feedback you cannot close a control loop, the best you can do is feed-forwards to compensate for known factors.

2- Mark set the Microseconds delay to 1000, I set it to 2600 to get approximately 50 Hz, how to accurately calculate the delay for 50Hz?

delayMicroseconds() isn't the thing to use for accuracy, code waiting for micros() to reach a target time and increment the target time each time round,
then you compensate for time spent running code. Timing can only be as accurate as the system clock,
if thats not a quartz crystal or oscillator you have to expect a percent or so variation.

3- To drive 6-pulse IGBT, I want to use three IR2110 drivers, but as I found in its datasheet I need a H and L input for each phase to fire H and L output from the driver for each IGBT pairs. But on the code output I only have three output for 3 phase. So how to produce H and L signal for each phase?

Many thanks for your helps.

You'll need a high-low MOSFET driver with single input and automatic dead-time to drive from 3 signals.
Most let you determine the deadtime in software as this is the most flexible way.

Regardless of the feedback, I tried do use a not gate (2n3904) to generate Linput for driver IC in addition to isolation using 4n35 optocoupler. The schematic digaram of the circuit is attached for one phase. Note that pin5 4n35 is connected to 5vdc through a 1k resistor. Is it ok or has problem?

Regards.

I built the circuit and it is working fine when I apply a square wave and its inverted signal using simple low-high command with 500us dead-time on pin 11 and 12 for one phase circuit. But the problem is the generated sine wave and its inverted signal using following modified code. When I apply it to the circuit through 2 optocouplers, they burn IR2110. The reason is that the sine wave has cross its invert in some points at each period which cause short on high and low mosfets. So how to solve the problem? Should I convert sine waves to square wave or what and how?

// For the UNO et al.
#define PERIOD 250   // 250 cycles = 15.625us for each half of waveform, 32kHz
#define HALF 125     // half the period is the default PWM threshold - gives square wave.
#define MAXAMP 31

static unsigned int ocr3a, ocr3b, ocr1a; // auxiliary variables to store obl. fillings
static unsigned int ocr1b, ocr2a, ocr2b; // ^

void setup_timers ()
{

cli();
  TCCR1A |= _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10);
  TCCR1B |= _BV(CS11); // preskaler 8  | _BV(WGM02)
  TIMSK1 |= _BV (TOIE1);                                                                   
 
  TCCR2A |= _BV(COM2A1) | _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B |= _BV (CS21); // preskaler 8 //  | _BV(WGM02)
 
  TCCR3A |= _BV(COM3A1) | _BV(COM3B0) | _BV(COM3B1) | _BV(WGM30);
  TCCR3B |= _BV(CS31); // preskaler 8  | _BV(WGM02)
 
  TCNT1L = 0;
  TCNT2 = 0;
  TCNT3L = 0;
 sei();
}


void setup ()
{
  Serial.begin(57600);
  setup_cosines () ;
  setup_timers () ;


 pinMode(2, OUTPUT); // OC0A Arduino Mega2560 pin 13
  pinMode(5, OUTPUT); // OC0B Arduino Mega2560 pin 4
  pinMode(11, OUTPUT); // OC1A Arduino Mega2560 pin 11 u
  pinMode(12, OUTPUT); // OC1B Arduino Mega2560 pin 12 uu
  pinMode(10, OUTPUT); // OC2A Arduino Mega2560 pin 10
  pinMode(9, OUTPUT); // OC2B Arduino Mega2560 pin 9
  
  pinMode (0, INPUT) ; // pot pin
  pinMode(A7, OUTPUT); //LED out pin
  pinMode(A5,OUTPUT); //Sensor VCC pin
  pinMode(A3,INPUT); //Sensor Input pin
  pinMode(A9,INPUT); //Sensor Input pin
  pinMode(A10,INPUT); //Sensor Input pin
}

volatile byte u = HALF ;
volatile byte v = HALF ;
volatile byte w = HALF ;
volatile byte uu = 0 ;
volatile byte vv = 0 ;
volatile byte ww = 0 ;


ISR (TIMER1_OVF_vect)   // overflow triggers at BOTTOM, update all the compare regs, which are sampled at TOP
{

    OCR1AL = u; // pin 11
    OCR1BL = uu ; // pin 12
    OCR2A = v; // pin 10
    OCR2B = vv ; // pin 9
    OCR3AL = w; // pin 5
    OCR3BL = ww ; // pin 2

}

#define  DEG_360  0x200             //512
#define  DEG_120  0x0AB             //171

char cosine_tab [DEG_360+1] ;  // fails to work if less than 0x202.

void setup_cosines ()
{
  for (int i = 0 ; i < 0x202 ; i++)   //514
  {
    float a = i * 6.283185 / 0x200 ;

    if (i <= DEG_360)
      cosine_tab [i] = round (127.0 * cos (a)) ;
      
  }
}

/////////////////////////////////////////////////
unsigned int phase = 0 ;
int pp = 0;
int freq ;        ////0
int amplitude = MAXAMP ;
float P = 0;        //V/F constant corrector coefficient
/////////////////////////////////////////////////
long startTime = 0;
int state, prevState = 0;
int sensor = 0;
long counter = 0;
double Ff = 0;
long sample_time;
int magnet_number;       
int sensore_output_voltage = 1000;
int prim_rpm = 0;
long sec_rpm = 0;
float  pot_co = 0;
int u1;
int u2;
long samp = 0;
/////////////////////////////////////////////////

int my_cosine (int ph)
{
  ph &= DEG_360-1 ;
  int res = cosine_tab [ph] ;
//  amplitude = P * amplitude;             //8=V/F constant for V=400v and F=50Hz
  res *= amplitude ;
  return (res + 0x0F) >> 5 ;

}

void loop ()
{

sensor = 0;
  Ff = 0;
  state = 0;
  prevState = 0;
  counter = 0;
  startTime = millis();
  sample_time = 10;        //5000 for 5 sec Loop for sample duration of sec
  magnet_number = 1;       //is number of magnets per revulotion
  
  //enable sensor and turn on LED when touched.
  digitalWrite(A5, HIGH);
//   Serial.println("Measuring...");

  //Loop for sample duration of 10 sec
  while((millis() - startTime) < sample_time)
  {
    sensor =  analogRead(A3);
    samp=millis();
    
//    Serial.print("sensor = "); Serial.println(sensor);
    if (sensor > sensore_output_voltage)  //sensore output voltage
    {
    state = 1;
           
    }
    else
    state = 0;
     digitalWrite(A7,state); // Blinking LED when sensor Activated
//
    //On change of state increment counter.
    //A change in state twice represents one revolution
    if(state != prevState)
    {
      counter++;
      prevState = state;

    }


    pot_co = map(analogRead(A0),0,1023,2500,50);
    pot_co = pot_co / 50.0;
    sec_rpm = prim_rpm / pot_co;
    freq = map(sec_rpm, 10, 1500, 0, 100);
    freq = 1    ;
    
    
  phase += freq ;

  int newu =  my_cosine (phase) ;
  int newv = my_cosine (phase - DEG_120) ;
  int neww = - newu - newv ;
  
  newu += HALF;
  newv += HALF;
  neww += HALF;

noInterrupts () ;  // interrupt-safe updating of u,v,w
  
  
  u = newu + 1 ;  // no masking of interrupts needed as u,v,w variables are single byte each.
  v = newv + 1 ;
  w = neww + 1 ;

  uu = newu - 1;
  vv = newv - 1;
  ww = neww - 1;

interrupts () ;

  delayMicroseconds (2000) ;    
  
  }
   digitalWrite(A7,LOW);
  digitalWrite(A5, LOW);
  
  counter = counter / 2; // 12*5sec=60sec
   
  prim_rpm = counter / magnet_number ;
//  prim_rpm = 1500;
//    

}

Maslord:
Regardless of the feedback, I tried do use a not gate (2n3904) to generate Linput for driver IC in addition to isolation using 4n35 optocoupler. The schematic digaram of the circuit is attached for one phase. Note that pin5 4n35 is connected to 5vdc through a 1k resistor. Is it ok or has problem?

Regards.

I can’t read the component values, for instance the resistors around the inverting transistor could be R100,
100, 100k, really can’t make it out. R100 means 0.1 ohm, for instance.

Since you are using a driver without shoot-through prevention, you have to provide deadtime when
switching, which necessitates using two Arduino pins per half-H-bridge with appropriate timing.

If one MOSFET is still turning off when you enable the other, bang they both pop… (or in marginal
cases rapidly get very hot), as you are shorting the supply directly to ground through both devices.

Using a high-low driver with shoot-through prevention is simpler to get right. Checkout IRS2004 for
instance.

Deadtime is between the high and low MOSFETs on a single arm of the bridge, and is typically of
the order of a few 100ns, not us.

Your optocoupler is too slow for switching MOSFETs, its has a switching time of 10µs,
you need a fast logic optocoupler for such purposes, on the <100ns timescale of operation,
not a phototransistor based one.

BTW I said use a high-low driver with automatic dead time generation in my post #27 already…

MarkT:
I can’t read the component values, for instance the resistors around the inverting transistor could be R100,
100, 100k, really can’t make it out. R100 means 0.1 ohm, for instance.

Since you are using a driver without shoot-through prevention, you have to provide deadtime when
switching, which necessitates using two Arduino pins per half-H-bridge with appropriate timing.

If one MOSFET is still turning off when you enable the other, bang they both pop… (or in marginal
cases rapidly get very hot), as you are shorting the supply directly to ground through both devices.

Using a high-low driver with shoot-through prevention is simpler to get right. Checkout IRS2004 for
instance.

Deadtime is between the high and low MOSFETs on a single arm of the bridge, and is typically of
the order of a few 100ns, not us.

Your optocoupler is too slow for switching MOSFETs, its has a switching time of 10µs,
you need a fast logic optocoupler for such purposes, on the <100ns timescale of operation,
not a phototransistor based one.

BTW I said use a high-low driver with automatic dead time generation in my post #27 already…

Thank you Mark for the reply. Regarding to resistors value, the gate source is 1kohm, gate resistor is 10 ohm, resistor before transistor, and pin 1 of optocoupler is 1kohm.
Regardless of those element’s values and deadtime, the main problem is the the pwm generates a complete sine wave (0 to 255) for each phase and its inverted signal which means the signal and its invert cross each other somewhere around half of period (127). So my main question is, can I apply sine wave as gating signal to IR2110 and mosfets or I have to translate the sine wave to square one or what? Deadtime is the next step. It is appreciated if you can clarify my ambiguity on gating signal.