Stopwatch lib and PWM software conflicts?

Hello all,
I am quite new to arduino so this might a very simplistic, or maybe not..., either way i am not going to have much hair left in a weeks time.
Firstly what it does/should do.
The concept is to measure the duration of a squarewave and based on the length (1 sec, 3 sec, 5 sec,7 sec) activate a solenoid via n-ch mosfet. I have done this via interrupts looking for the rising edge (start timer) then falling edge (stop the timer). Everything working perfectly.
The problem came when i encountered a grounding problem and had to make a dc-dc converter. In short, I just made a 'dirty' quick fix, using another n-ch mosfet to do the switching for me(again this works fine on its own). Then assigned a pwm to take care of that, when i did this however i screwed up my first part of the program. Once i take out the pwm it works fine again... where is the problem???
Its doesnt appear to be the hardware. I checked the PWM it seems fine, i can upload o-scope pictures.
IF this helps, i noticed that if i enable my pwm but just don't connect that pin to anything else (o-scope, mosfet) it works fine but then obviously the dc-dc converter does work.

I am using an Arduino Uno R3.
PWM is connected on pin 11 (using timer 2
solenoid outputs are 4-7
interrupts on pins 2,3.
My main code is as follows

#include <StopWatch.h>

StopWatch SW;

int PWMPin = 11;
void setup() {                
          // initialize required digital pins as an output / input
          
          pinMode(13, OUTPUT); // LED response - onboard arduino      
     
          //pinMode(11,OUTPUT);
          //analogWrite(PWMPin, 127); // PWM for DC - DC converter
         
          attachInterrupt(1, Timer_start, RISING); 
          attachInterrupt(0, Phone_Signal, FALLING); 
          // enables interrupt on 'int0' (PIN 2 & 3 on dev board) & sets the interrupts to trigger on a rising and falling input
          
          //Assigning pins to be output to solenoids
          pinMode(4, OUTPUT);   
          pinMode(5, OUTPUT);   
          pinMode(6, OUTPUT);
          pinMode(7, OUTPUT);          
          
}

void loop() 
{

}
void Timer_start() // starts the timer
{
                 SW.reset();	// resets the measurement
                 SW.start();	// start / continue the measurement
}

void Phone_Signal()
{       
              SW.stop();	// stops the measurement

                             if (SW.value() < 1500 && SW.value() > 50) //i want 1000 mS just giving it alot of room (pulse is 1 sec exactly)
                                {
                                  digitalWrite(4,HIGH);
                                  delay(500);
                                  digitalWrite(4,LOW);
                                }
                      else if (SW.value() < 4000 && SW.value() > 1500) //i want 3000 mS just giving it alot of room (pulse is 3 sec exactly)
                                 {
                                   digitalWrite(5,HIGH);
                                   delay(500);
                                   digitalWrite(5,LOW);
                                 }
                                
                       else if (SW.value() < 5100 && SW.value() > 4000)//i want 5000 mS just giving it alot of room (pulse is 5 sec exactly)
                                 {
                                   digitalWrite(6,HIGH);
                                   delay(500);
                                   digitalWrite(6,LOW);
                                 }
                                 
                        else if (SW.value() < 8000 && SW.value() > 5100)//i want 7000 mS just giving it alot of room (pulse is 7 sec exactly)
                                 {
                                   digitalWrite(7,HIGH);
                                   delay(500);
                                   digitalWrite(7,LOW);
                                 }
                                  else if (SW.value() > 8000 || SW.value() == 0 )//Greater than 8000 mS or timer started but is out of range
                                 {
                                   error();
                                 }
}
void error() // LED is on Constantly if there is an error
{
            digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
            delay(50000);
            digitalWrite(13, LOW); 
}

I am using the stopwatch library which can be found here

http://playground.arduino.cc/Code/Stopwatch

What am i missing? As far as i can tell the stopwatch is using timer one, whilst the pwm which i am using is using timer 2?
Thanks so much in advance, please let me know if i can provide any additional information
Regards

Chris

Phone_Signal is an interrupt service routine. You need to understand what you can, and can not do, in an ISR. delay() is a can not do.

delay() is a can not do.

So if i were to call a function from inside the ISR then would that still be classified as 'in the ISR'. I am thinking its not allowed. Ill edit the code, thanks so much for your input, really appreciated it. I am thinking of turning off the solenoids inside the main loop. But that does explain quite a bit of the 'random' events i was getting. As an electrical engineer i just have to ask..., why can you not use the delay() function within the ISR? aren't you just calling a function from within another?
Neways ill let you know what happens
Once again thanks for your reply, really appreciate it :slight_smile:

So if i were to call a function from inside the ISR then would that still be classified as 'in the ISR'.

Yes.

why can you not use the delay() function within the ISR?

What does delay do? It waits until the specified time has elapsed. How does it know that? The clock ticks, of course. Except that clock ticks involved interrupts, which don't happen while your interrupt service routine is handling an interrupt.

Ah, i see. So basically once your ISR (phone_signal, in this case) begins all other interrupts will 'shelved' or raise their respective flags in their respective registers. Hence those interrupts (delay() ) will only occur after the ISR Phone_signal has been completed... brilliant understood.
I can see you have been doing that for a while, probably seems obvious to you, yet it didn't even occur to me.
Thanks so much PaulS
I might have some hair next week after all... :slight_smile:

Hi Paul, i come with sad tidings, and glad.
Good news is that it runs a lot more stable, due to the delay() function removal from the ISR.
The bad news however is that its till not operating correctly. I have uploaded a few pictures (o-scope results) to help explain.
I will just refer to them as 1,2 and 3.
Coding was kept the same for all 3 photo's.
In 1, it shows correct operation. Blue line is my 'squarewave', yellow is signal to solenoid. Everything happy.
*Note - pwm wire to n-chan, mosfet is simply not connected

2, shows the pwm operating (measured directly at the uno pin) (yellow), and blue the input signal again.
*Note -The solenoid did not operate

3, is where things got interesting, it has the exact same configuration as in 2, blue line is the input squarewave/tone to the MC, the yellow line is VCC to the MC,Solenoid, transformer being switched. The second tone/pulse is actually the shutter sound from the phone. The odd thing is that the solenoid was triggered by the second pulse?
This makes me think that it must be a timer/clock issue. The hardware seems to operate correctly. This theory is also supported by the test LED (pin 13) which goes off when the timer value (SW.value) exceeds 8 seconds (this should never happen as the longest pulse is 7 seconds) yet when the pwm is plugged in (used to switch the n-channel mosfet) this LED lights up (its the only time that it lights up).
... Help? I am so lost!

Ps my updated code is as follows

//Chris
#include <StopWatch.h>

StopWatch SW;

int PWMPin = 11;
void setup() {                
          // initialize required digital pins as an output / input
          
          pinMode(13, OUTPUT); // LED response - onboard arduino           
          pinMode(11,OUTPUT);
          
          analogWrite(PWMPin, 127); // 50% duty cycle, max power conversion to phone charger
         
          attachInterrupt(1, Timer_start, RISING); 
          attachInterrupt(0, Phone_Signal, FALLING); 
          // enables interrupt on 'int0' (PIN 2 & 3 on dev board) & sets the interrupts to trigger on a rising and falling input
          
          //Assigning pins to be output to solenoids
          pinMode(4, OUTPUT);   
          pinMode(5, OUTPUT);   
          pinMode(6, OUTPUT);
          pinMode(7, OUTPUT);          
          
}

void loop()
{
  
  if (digitalRead(4) == HIGH || digitalRead(5) == HIGH ||digitalRead(6) == HIGH ||digitalRead(7) == HIGH)
    {
      noInterrupts(); //disbales interrupts
      
      delay(1000); // ensuring solenoid is allowed to fully open.
      
      // resets all solenoids - off
      digitalWrite(4,LOW);
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      
      interrupts(); // enables interrupts again and waits for next interrupt
    }

}


void Timer_start() // starts the timer
{
                 SW.reset();	// resets the measurement
                 SW.start();	// start / continue the measurement
}

void Phone_Signal()
{       
              SW.stop();	// stops the measurement

              
                             if (SW.value() < 1500 && SW.value() > 50) //i want 1000 mS just giving it alot of room (pulse is 1 sec exactly)
                                {
                                  digitalWrite(4,HIGH);
                                }
                                else if (SW.value() < 4000 && SW.value() > 1500) //i want 3000 mS just giving it alot of room (pulse is 3 sec exactly)
                                 {
                                   digitalWrite(5,HIGH);
                                 }
                                
                         else if (SW.value() < 5100 && SW.value() > 4000)//i want 5000 mS just giving it alot of room (pulse is 5 sec exactly)
                                 {
                                   digitalWrite(6,HIGH);
                                 }
                                 
                                 else if (SW.value() < 8000 && SW.value() > 5100)//i want 7000 mS just giving it alot of room (pulse is 7 sec exactly)
                                 {
                                   digitalWrite(7,HIGH);                                   
                                 }
                                  else if (SW.value() > 8000 || SW.value() == 0 )//Greater than 8000 mS or timer started but is out of range
                                 {
                                   error();
                                 }
}

void error() // LED is on Constantly if there is an error
{
            digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
}

      noInterrupts(); //disbales interrupts
      
      delay(1000); // ensuring solenoid is allowed to fully open.

delay() relies on interrupts. Turning interrupts off for so long is really a bad idea.

Hi Paul,
Sorry for the silly mistake ( i seem to be making a lot of them).
I changed the code so that the interrupts are being disabled after the delay, is was really not needed to be after the noInterrupts();, that was just idiotic/careless of me.

//Chris
#include <StopWatch.h>

StopWatch SW;

int PWMPin = 11;
void setup() {                
          // initialize required digital pins as an output / input
          
          pinMode(13, OUTPUT); // LED response - onboard arduino           
          pinMode(11,OUTPUT);
          
          analogWrite(PWMPin, 127); // 50% duty cycle, max power conversion to phone charger
         
          attachInterrupt(1, Timer_start, RISING); 
          attachInterrupt(0, Phone_Signal, FALLING); 
          // enables interrupt on 'int0' (PIN 2 & 3 on dev board) & sets the interrupts to trigger on a rising and falling input
          
          //Assigning pins to be output to solenoids
          pinMode(4, OUTPUT);   
          pinMode(5, OUTPUT);   
          pinMode(6, OUTPUT);
          pinMode(7, OUTPUT);          
          
}

void loop()
{
  
  if (digitalRead(4) == HIGH || digitalRead(5) == HIGH ||digitalRead(6) == HIGH ||digitalRead(7) == HIGH)
    {

      delay(1000); // ensuring solenoid is allowed to fully open.
      noInterrupts(); //disbales interrupts
      
      // resets all solenoids - off
      digitalWrite(4,LOW);
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      
      interrupts(); // enables interrupts again and waits for next interrupt
    }

}


void Timer_start() // starts the timer
{
                 SW.reset();	// resets the measurement
                 SW.start();	// start / continue the measurement
}

void Phone_Signal()
{       
              SW.stop();	// stops the measurement

              
                             if (SW.value() < 1500 && SW.value() > 50) //i want 1000 mS just giving it alot of room (pulse is 1 sec exactly)
                                {
                                  digitalWrite(4,HIGH);
                                }
                                else if (SW.value() < 4000 && SW.value() > 1500) //i want 3000 mS just giving it alot of room (pulse is 3 sec exactly)
                                 {
                                   digitalWrite(5,HIGH);
                                 }
                                
                         else if (SW.value() < 5100 && SW.value() > 4000)//i want 5000 mS just giving it alot of room (pulse is 5 sec exactly)
                                 {
                                   digitalWrite(6,HIGH);
                                 }
                                 
                                 else if (SW.value() < 8000 && SW.value() > 5100)//i want 7000 mS just giving it alot of room (pulse is 7 sec exactly)
                                 {
                                   digitalWrite(7,HIGH);                                   
                                 }
                                  else if (SW.value() > 8000 || SW.value() == 0 )//Greater than 8000 mS or timer started but is out of range
                                 {
                                   error();
                                 }
}

void error() // LED is on Constantly if there is an error
{
            digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
}

The bad news is that is it still not operating correctly. My as a clue to what i could be, my test led (pin 13) goes of on every pulse, hence i can tell the MC is picking up the pulse, its just that the SW.value() is greater than 8000 (consistently)? I really dont understand how this could be, because according to the stopwatch header and .ccp file the default setting is in milliseconds and i measured the pulse via the scope, very close to 1 second exactly hence where could the error be coming from?
Thanks again for all your help.
Much appreciated
Regards
Chris

      noInterrupts(); //disbales interrupts
      
      // resets all solenoids - off
      digitalWrite(4,LOW);
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      
      interrupts(); // enables interrupts again and waits for next interrupt

I don't understand why you think you need to disable interrupts while you turn some pins off.

My as a clue to what i could be, my test led (pin 13) goes of on every pulse, hence i can tell the MC is picking up the pulse, its just that the SW.value() is greater than 8000 (consistently)?

Which pulse are you referring to? What is physically connected to pins 2 and 3?

The StopWatch page that you provided a link to shows a sketch that illustrates how to use millis(). It does not provide a library, that I can see. Post a link to where you got the StopWatch library, or post the header and source files.

Pins 2 & 3 have the input signal connected to them, i used both pins one for rising edge one for falling (same input hence they are effectively connected on the same node. I know i could use Change, instead of rising and falling edges, i just stuck to what i knew from before rising edge and falling).
The pulse which i was refering to is the blue line from the pictures 2,3 i uploaded (i believe i only used the B input for the input signal). As you can see in picture 3 there is also a second shorter (time wise) 'pulse' this is the camera shutter sound, i have actually now turned the shutter sound off hence it will only have the one square wave pulse. I basically converted an tone into a square wave so that i can measure the length of the tone (coming from a cellphone)
My appologies,
http://playground.arduino.cc/Code/StopWatchClass
, has all of the code, .h and .cpp.
As to the reason for turning off the interrupts... i can now see how silly that actually is, but my thought process was to ensure that the solenoids turn off, but looking at it now it does absolutely nothing. I will remove it.
Sorry for the late response i was very exhausted yesterday. I will draw up a schematic tonight and also at 'test points' give o-scope measurements.
Thanks so much for your time
Kind Regards
Chris

The StopWatch class does nor use a timer, so there is nothing to interfere with PWM. Looking back at your problem statement, it appears that connecting something to the pin that you are PWMing causes problems, but with nothing connected, everything is fine. That suggests to me that the problem is that whatever you are connecting is drawing too much current.

I'd try using an LED with current limiting resistor in the PWM pin. Does that cause the problem you are trying to track down?

There is a big difference between what the stop() and reset() methods do. It's not clear to me which one you need to be calling.

The square wave that you are measuring - where does it come from? How do you know how long the pulses are supposed to be?

I can double check the pwm wires, the thing that counters that theory is that when i plug the pwm in, it works, i know this because i get a voltage on the secondary side of the transformer (which tells me that the primary is switching) i then rectify and use to recharge the phone, this is shown in picture 2 that i uploaded. (blue line in picture 2 is the input square wave). But i sure can double check the pwm circuit.

I am wondering, the VCC of the MC and the Voltage accross the transformers primarys is the same (same node), could it be that in the 'on' cycle of the pwm when i first switch on my transformer that is actually causes the voltage to dip caused by the TX inrush current (short Spike). The reason why i say short spike is because i checked this and on my cheap O-scope (at 20khz sampling) appears to be steady during the switching? But as i said the timer appears to run for over 8 seconds, but ill try everything i can think of and then post a schematic and diagrams and pictures and anything else i can think of.

The square wave is a tone which comes from the cell phone's audio jack. I use op-amps to alter the 'tone' into a square wave since this is much easier to measure tone length. The tone length is coded into the andriod app. Ultimately the tone length is chosen via txt/sms message sent to the phone which the app picks up the predefined (key word) and sends the corresponding tone length out via the audio jack, MC measures length and based on the tone length activates the solenoid.

Hope this answers a few of your questions

Regards
Chris

Ps
sorry for the bad drawing but here is a paint sketch of what pwm pin 'sees' , will upload better diagram when i get home.
Thanks so much for your help, please don't hesitate to ask for any additional info i can provide
Cheers
Chris

PWM pin.png

I hope this helps visualize what i am making/trying to do.
With the dip in voltage (of the tone shown in the second picture), i have put int a capacitor accross the input voltage thus helping to 'cover' the inrush current. This appears to be working as the input signal is not dipping anymore.
Overall the current status of the project is that it works one in 3-4 times, obviously not good enough. However it is starting to work. The thing that i believe could be a clue to the problem is the test LED on pin 13. This led only gets activated in the error() function. it only gets set high if the stopwatch value is above 8000. This seems to be the case a lot of the time since for every tone, the led lights up.
Once again thanks for your help, i would really appreciate any ideas.
Kind regards
Chris

Ps latest code

//Chris
#include <StopWatch.h>

StopWatch SW;

int PWMPin = 11;
void setup() {                
          // initialize required digital pins as an output / input
          
          pinMode(13, OUTPUT); // LED response - onboard arduino           
          pinMode(11,OUTPUT);
          
          analogWrite(PWMPin, 127); // 50% duty cycle, max power conversion to phone charger
         
          attachInterrupt(1, Timer_start, RISING); 
          attachInterrupt(0, Phone_Signal, FALLING); 
          // enables interrupt on 'int0' (PIN 2 & 3 on dev board) & sets the interrupts to trigger on a rising and falling input
          
          //Assigning pins to be output to solenoids
          pinMode(4, OUTPUT);   
          pinMode(5, OUTPUT);   
          pinMode(6, OUTPUT);
          pinMode(7, OUTPUT);          
          
}

void loop()
{
  
  if (digitalRead(4) == HIGH || digitalRead(5) == HIGH ||digitalRead(6) == HIGH ||digitalRead(7) == HIGH)
    {

      
      delay(1000); // ensuring solenoid is allowed to fully open.
      
      //noInterrupts(); //disbales interrupts
      
      // all solenoids - off
      digitalWrite(4,LOW);
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      
      //interrupts(); // enables interrupts again and waits for next interrupt
    }

}


void Timer_start() // starts the timer
{
                 SW.reset();	// resets the measurement
                 SW.start();	// start / continue the measurement
}

void Phone_Signal()
{       
              SW.stop();	// stops the stopwatch

              
                             if (SW.value() < 1500 && SW.value() > 50) //i want 1000 mS just giving it alot of room (pulse is 1 sec exactly)
                                {
                                  digitalWrite(4,HIGH);
                                }
                                else if (SW.value() < 4000 && SW.value() > 1500) //i want 3000 mS just giving it alot of room (pulse is 3 sec exactly)
                                 {
                                   digitalWrite(5,HIGH);
                                 }
                                
                                else if (SW.value() < 5100 && SW.value() > 4000)//i want 5000 mS just giving it alot of room (pulse is 5 sec exactly)
                                 {
                                   digitalWrite(6,HIGH);
                                 }
                                 
                                 else if (SW.value() < 8000 && SW.value() > 5100)//i want 7000 mS just giving it alot of room (pulse is 7 sec exactly)
                                 {
                                   digitalWrite(7,HIGH);                                   
                                 }
                                  else if (SW.value() > 8000 || SW.value() == 0 )//Greater than 8000 mS or timer started but is out of range
                                 {
                                   error();
                                 }
  

}

void error() // LED is on Constantly if there is an error
{
            digitalWrite(13, HIGH);   // turn the LED on 
}