Probelms w/ accurate button readings when using interrupts (waveform generator)

Hello,

I am building a custom waveform generator using Arduino. It has three variables: wave type, duty cycle and frequency. I successfully built this device using hardware and two interrupt pins. One interrupt button would toggle duty cycle and the other interrupt button would toggle wave type and simultaneously check the analog reading on a potentiometer to control frequency (because there are only two interrupt pins on the Arduino uno).

Now I am trying to control the generator using signals from another device rather than hardware. I have changed the code such that theoretically one interrupt should check all three signals and change (or not change) the wave accordingly. When the interrupt is implemented, if the duty cycle is HIGH the duty cycle will toggle. If the wave type signal is HIGH it will toggle wave type. It will check the analog reading on the potentiometer each time the interrupt is implemented. I am testing by still using a potentiometer but only connecting the duty cycle and wave type pins to voltage or ground rather than a button. Code and electrical connections have all been checked by me at least 50 times and by two other people in my lab and none of us can figure it out!

Here are the problems that arise:

-duty cycle and frequency only change when wave type pin is HIGH
-when wave type pin is HIGH, duty cycle pin is always read as HIGH also
-duty cycle does not change until interrupt is executed twice (with duty cycle pin on HIGH both times)

If you have any idea what's going on here or have suggestions on how to fix this but please help!!!

Thanks in advance,

Christina

Hi, welcome to the forum.

Please read this : http://forum.arduino.cc/index.php/topic,148850.0.html

To have some idea of what you are doing, we would like to see schematics, the full sketch, and perhaps a photo.
You are using an Arduino Uno ?

What kind of debounce do you use ?

The Arduino Uno has PCINT interrupts on every pin : http://www.arduino.cc/en/Hacking/PinMapping168
But that needs an extra library : GitHub - GreyGnome/PinChangeInt: Pin Change Interrupt library for the Arduino

Most of us don't use an interrupt for a button. If the sketch is well written, there should be no long delays, and the code in the loop() could check the buttons every 10ms and do some debounce.

To answer your question :
30% change : A bug in the sketch.
20% change : Bad contacts on the breadboard.
10% change : It could be a faulty Uno board, if you bought a cheap clone.
40% change : something else
There is a change that the above numbers are totally wrong :wink:

Hi Peter_n, thanks for the quick response and sorry for the slow response on my part. :blush:

Yes I am using and Arduino Uno. I used hardware debouncing with a pull up resistor, a capacitor across the button, and an inverting schmitt trigger.

I can get a picture uploaded tomorrow, but the picture uploaded is a schematic of the interrupt debounce. other connections on the board are pretty standard.

From what you're saying it seems that you think this is a hardware problem rather than a code problem, is that right? Do you think there's any way this could be a bug with my code even though it was working before I converted it to just one interrupt instead of two? This is my code for when the interrupt is executed:

void checkSignals()
{

//FREQUENCY CHECK-----------------------------------------------------------------------------------------------------
val = analogRead(freq); //val is used to determine frequency

//DUTY CYCLE CHECK----------------------------------------------------------------------------------------------------
if (digitalRead(dutyCyclePin)==HIGH) //toggle duty cycle if signal is high
{
if (DCbuttonPushCounter != 9) { DCbuttonPushCounter++; }
else { DCbuttonPushCounter = 1; } // reset to first (default) wave type if more than 10

DCbuttonState = DCbuttonPushCounter;

switch (DCbuttonPushCounter)
{
case 1:
dutyCycleMultiplierHigh = 0.1;
dutyCycleMultiplierLow = 0.9;
signalReceived = 1;
break;
case 2:
dutyCycleMultiplierHigh = 0.2;
dutyCycleMultiplierLow = 0.8;
signalReceived = 1;
break;
case 3:
dutyCycleMultiplierHigh = 0.3;
dutyCycleMultiplierLow = 0.7;
signalReceived = 1;
break;
case 4:
dutyCycleMultiplierHigh = 0.4;
dutyCycleMultiplierLow = 0.6;
signalReceived = 1;
break;
case 5:
dutyCycleMultiplierHigh = 0.5;
dutyCycleMultiplierLow = 0.5;
signalReceived = 1;
break;
case 6:
dutyCycleMultiplierHigh = 0.6;
dutyCycleMultiplierLow = 0.4;
signalReceived = 1;
break;
case 7:
dutyCycleMultiplierHigh = 0.7;
dutyCycleMultiplierLow = 0.3;
signalReceived = 1;
break;
case 8:
dutyCycleMultiplierHigh = 0.8;
dutyCycleMultiplierLow = 0.2;
signalReceived = 1;
break;
case 9:
dutyCycleMultiplierHigh = 0.9;
dutyCycleMultiplierLow = 0.1;
signalReceived = 1;
break;
}
}

//WAVE TYPE CHECK-----------------------------------------------------------------------------------------------------
if (digitalRead(wavePin)==HIGH) // toggle wave type if signal is high
{
signalReceived = 1;

switch (WbuttonPushCounter)
{
case 0:
wavenumber = 0;
WbuttonPushCounter= 1;
break;
case 1:
wavenumber = 1;
WbuttonPushCounter=0; // reset to first (default) wave type
break;
}
}
else if (digitalRead(wavePin)==LOW)
{
switch (WbuttonPushCounter)
{
case 0:
wavenumber = 0;
WbuttonPushCounter=0;
break;
case 1:
wavenumber = 1;
WbuttonPushCounter=1;
break;
}
}

}//end check signals interrupt--------------------------------------------------------------------------------------------

Screen Shot 2015-06-25 at 12.31.21 PM.png

oops sorry I forgot to put it in code form! :

void checkSignals()
{
  
//FREQUENCY CHECK----------------------------------------------------------------------------------------------------- 
   val = analogRead(freq);
   
  
//DUTY CYCLE CHECK----------------------------------------------------------------------------------------------------
  if (digitalRead(dutyCyclePin)==HIGH)
  {
        if (DCbuttonPushCounter != 9) { DCbuttonPushCounter++;  }
        else { DCbuttonPushCounter = 1;   }                       // reset to first (default) wave type if more than 10 
        
        DCbuttonState = DCbuttonPushCounter;    
       
    
    switch (DCbuttonPushCounter) 
    {
      case 1: 
        dutyCycleMultiplierHigh = 0.1; 
        dutyCycleMultiplierLow = 0.9; 
        signalReceived = 1; 
        break; 
      case 2: 
        dutyCycleMultiplierHigh = 0.2; 
        dutyCycleMultiplierLow = 0.8;  
        signalReceived = 1; 
        break; 
      case 3: 
        dutyCycleMultiplierHigh = 0.3; 
        dutyCycleMultiplierLow = 0.7;  
        signalReceived = 1; 
        break; 
      case 4: 
        dutyCycleMultiplierHigh = 0.4; 
        dutyCycleMultiplierLow = 0.6; 
        signalReceived = 1; 
        break; 
      case 5: 
        dutyCycleMultiplierHigh = 0.5; 
        dutyCycleMultiplierLow = 0.5; 
        signalReceived = 1; 
        break; 
      case 6: 
        dutyCycleMultiplierHigh = 0.6; 
        dutyCycleMultiplierLow = 0.4; 
        signalReceived = 1; 
        break; 
      case 7: 
        dutyCycleMultiplierHigh = 0.7; 
        dutyCycleMultiplierLow = 0.3; 
        signalReceived = 1; 
        break; 
      case 8: 
        dutyCycleMultiplierHigh = 0.8; 
        dutyCycleMultiplierLow = 0.2; 
        signalReceived = 1; 
        break; 
      case 9: 
        dutyCycleMultiplierHigh = 0.9; 
        dutyCycleMultiplierLow = 0.1;
        signalReceived = 1; 
        break; 
    }        
  }

  
  //WAVE TYPE CHECK----------------------------------------------------------------------------------------------------- 
  if (digitalRead(wavePin)==HIGH)
  {
      signalReceived = 1; 

           switch (WbuttonPushCounter)
           { 
             case 0:
                wavenumber = 0; 
                WbuttonPushCounter= 1;  
                break; 
             case 1:
                wavenumber = 1; 
                WbuttonPushCounter=0;                         // reset to first (default) wave type 
                break;         
           }
  }
  else if (digitalRead(wavePin)==LOW)
  {
           switch (WbuttonPushCounter)
           { 
             case 0:
                wavenumber = 0; 
                WbuttonPushCounter=0; 
                break; 
             case 1:
                wavenumber = 1; 
                WbuttonPushCounter=1; 
                break;         
           }
   }

  
}//end check signals interrupt--------------------------------------------------------------------------------------------

The Schmitt trigger is not needed. A digital input will read a good HIGH or LOW according to the input voltages in the datasheet.

I don't know if it is hardware or software. If you use a breadboard and the ground makes bad contact, anything is possible.

Because of this : http://snippets-r-us.com/ , I can not check if you have (very) large arrays or many text strings that could cause ram overflow. I don't know which variables are integer or float. I don't know how you have initialized things, and I don't know the use of the pins.

That it worked before does not mean that the code was okay. If for example an input is set at INPUT_PULLUP, but not as OUTPUT it is still possible to blink a led with it.

I don't see a need for interrupts in button handling. What else has to be done in loop()? How do you generate the wave?

i cannot post my entire code because it is too long but the code for creating the wave is below: I create simple square waves using high and low signals. interrupt is needed in order for the code to run quickly without being slowed by checking analog and digital readings each time. schmitt trigger and capacitor were needed in order to smooth the signal coming from the button, otherwise it would bounce multiple times. (picture now attached)

 // MAKE SIGNAL--------------------------------------------------------------------------------------------
     // based on frequency, duty cycle, and waveform parameters decided in the interrupt, create a signal output from pin 12

  
    while (wavenumber == 0)  //wave number 0 is square wave 
    {
      
      digitalWrite(pinoutput, HIGH); 
      delayMicroseconds(hightimesquare); 
      digitalWrite(pinoutput, LOW); 
      delayMicroseconds(lowtimesquare); 
    }
    
    while (wavenumber == 1)  //wave number 1 is arbitrary wave 
    {
        
         for (int i=0; i<firstWaveCycles; i++)
          {
            digitalWrite(pinoutput, HIGH); 
            delayMicroseconds(hightime1); 
            digitalWrite(pinoutput, LOW); 
            delayMicroseconds(lowtime1);
         } 
          for (int i=0; i<secondWaveCycles; i++)
          {
            digitalWrite(pinoutput, HIGH); 
            delayMicroseconds(hightime2); 
            digitalWrite(pinoutput, LOW); 
            delayMicroseconds(lowtime2);
          } 
    }

 

 
}//end main loop------------------------------------------------------------------------------------------

If you give us 5% information, we have to guess the other 95%. We might dream about Arduino, but we don't have crystal ball.