multi channel readings + pcm audio

Hello everyone!

I'm writing because i have problem with reading another pwm signal. I found that code on youtube and im trying to do some sound simulator. Everything works ok until i wanna put third channel as auxilary "start engine" button. I'm thinking that something is wrong with interruptions but i can't find what is wrong.

#include "idle.h"


boolean managedThrottle = true;     
boolean pwmThrottle = true;        // Takes a standard servo signal on pin 2 (UNO)
boolean engineOn = true;




// Stuff not to play with!
#define BASE_RATE 16000 // The base sample rate of the audio

#define DEFAULT_VOLUME 127      // Volume when in non managed mode
#define VOL_MIN 20              // Min volume in managed mode 0 - 127
#define VOL_MAX 127             // Max volume in managed mode 0 - 127
#define TOP_SPEED_MULTIPLIER 15 // RPM multiplier in managed mode, bigger the number the larger the rev range, 10 - 15 is a good place to start

#define SPEAKER 3                               // This is kept as 3, original code had 11 as option, but this conflicts with SPI
volatile uint16_t currentSmpleRate = BASE_RATE; // Current playback rate, this is adjusted depending on engine RPM
boolean audioRunning = false;                   // Audio state, used so we can toggle the sound system
uint16_t curVolume = 0;                         // Current digi pot volume, used for fade in/out
volatile uint16_t curEngineSample;              // Index of current loaded sample
uint8_t  lastSample;                            // Last loaded sample
int16_t  currentThrottle = 0;                   // 0 - 1000, a top value of 1023 is acceptable
uint8_t  throttleByte = 0;                      // Raw throttle position in SPI mode, gets mapped to currentThrottle
uint8_t  spiReturnByte = 0;                     // The current RPM mapped to a byte for SPI return
volatile int16_t pulseWidth = 0;                // Current pulse width when in PWM mode
volatile int16_t  pulseWidth2 = 0;  




void setup()
{
  Serial.begin(9600);
  if(managedThrottle) writePot(0);
  else writePot(DEFAULT_VOLUME);


  // pwm in setup, for a standard servo pulse
  pinMode(2, INPUT); // We don't want INPUT_PULLUP as the 5v may damage some receivers!
  if(pwmThrottle){   // And we don't want the interrupt firing when not in pwm mode
    attachInterrupt(0, getPulsewidth, CHANGE);
  }

  pinMode(4, INPUT);
  attachInterrupt(1, getPulsewidth2, CHANGE);
  startPlayback();
}




void loop()
{
  doPwmThrottle();
  manageSpeed();
  Serial.println(pulseWidth2);
}



void doPwmThrottle(){

  
    if(pulseWidth > 800 && pulseWidth < 2200){ // check if the pulsewidth looks like a servo pulse
      if(pulseWidth < 1000) pulseWidth = 1000; // Constrain the value
      if(pulseWidth > 2000) pulseWidth = 2000;

      if(pulseWidth > 1520) currentThrottle = (pulseWidth - 1500) *3;  // make a throttle value from the pulsewidth 0 - 1000
      else if(pulseWidth < 1470) currentThrottle = abs( (pulseWidth - 1500) *3);
      else currentThrottle = 0;
    }
  

}

void doengine(){
  if(pulseWidth2 > 1955) engineOn = true;
  else if(pulseWidth2 < 1200) engineOn = false;
  else engineOn = false;
  
}


void manageSpeed(){

  static int16_t prevThrottle = 0xFFFF;
  static int16_t currentRpm = 0;
  const  int16_t maxRpm = 18184;
  const  int16_t minRpm = 0;

  static unsigned long throtMillis;
  static unsigned long volMillis;

  // Engine RPM
  if(millis() - throtMillis > 5) {
    throtMillis = millis();

    if(currentThrottle +12 > currentRpm){
      currentRpm += 6;
      if(currentRpm > maxRpm) currentRpm = maxRpm;
      prevThrottle = currentThrottle;

    }
    else if(currentThrottle -15 < currentRpm){
      currentRpm -= 12;
      if(currentRpm < minRpm) currentRpm = minRpm;
      prevThrottle = currentThrottle;
    }

    if(currentRpm >> 2 < 255) spiReturnByte = currentRpm >> 2;
    else spiReturnByte = 255;
    if(currentRpm >> 2 < 0) spiReturnByte = 0;

    currentSmpleRate = F_CPU / (BASE_RATE + long(currentRpm * TOP_SPEED_MULTIPLIER) );
  }


  // Engine Volume
  if(millis() - volMillis > 50) {
    volMillis = millis();

    int vol = map(currentThrottle, 0, 1023, VOL_MIN, VOL_MAX);

    if(vol > curVolume) curVolume = vol;
    else {
      curVolume -= (curVolume/10);
      if(curVolume < VOL_MIN) curVolume = VOL_MIN;
    }

    int lastVolume = 0xFFFF;
    if(curVolume != lastVolume){
      lastVolume = curVolume;
      writePot(curVolume);
    }

  }

}


void writePot(uint8_t data){
  // This function should get a value from 0 - 127
  // It would be trivial to convert this to work with
  // an I2C device.

  if(data > VOL_MAX) data = VOL_MAX; // cap it just in case

}



void startPlayback()
{
  pinMode(SPEAKER, OUTPUT);
  audioRunning = true;

  // Set up Timer 2 to do pulse width modulation on the speaker pin.
  ASSR &= ~(_BV(EXCLK) | _BV(AS2));                         // Use internal clock (datasheet p.160)

  TCCR2A |= _BV(WGM21) | _BV(WGM20);                        // Set fast PWM mode  (p.157)
  TCCR2B &= ~_BV(WGM22);

  TCCR2A = (TCCR2A | _BV(COM2B1)) & ~_BV(COM2B0);           // Do non-inverting PWM on pin OC2B (p.155)
  TCCR2A &= ~(_BV(COM2A1) | _BV(COM2A0));                   // On the Arduino this is pin 3.
  TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10); // No prescaler (p.158)

  OCR2B = pgm_read_byte(&idle_data[0]);                     // Set initial pulse width to the first sample.

  // Set up Timer 1 to send a sample every interrupt.
  cli();

  TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);             // Set CTC mode (Clear Timer on Compare Match) (p.133)
  TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));             // Have to set OCR1A *after*, otherwise it gets reset to 0!

  TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10); // No prescaler (p.134)

  OCR1A = F_CPU / BASE_RATE;                                // Set the compare register (OCR1A).
                                                            // OCR1A is a 16-bit register, so we have to do this with
                                                            // interrupts disabled to be safe.

  TIMSK1 |= _BV(OCIE1A);                                   // Enable interrupt when TCNT1 == OCR1A (p.136)

  lastSample = pgm_read_byte(&idle_data[idle_len-1]);
  curEngineSample = 0;
  sei();


  uint8_t target = map(currentThrottle, 0, 1023, VOL_MIN, VOL_MAX); // Fadein the volume pot
  for(uint8_t i = 0; i < target; i ++){
    curVolume = i;
    writePot(curVolume);
    delay(1);
  }
}


void stopPlayback()
{
  // Fadeout the volume pot
  for(uint8_t i = curVolume; i > 0; i--){
    curVolume = i;
    writePot(i);
    delay(1);
  }

  audioRunning = false;

  TIMSK1 &= ~_BV(OCIE1A); // Disable playback per-sample interrupt.
  TCCR1B &= ~_BV(CS10);   // Disable the per-sample timer completely.
  TCCR2B &= ~_BV(CS10);   // Disable the PWM timer.

  digitalWrite(SPEAKER, LOW);
}



// Uses a pin change interrupt and micros() to get the pulsewidth at pin 2
void getPulsewidth(){
  unsigned long currentMicros = micros();
  boolean currentState = digitalRead(2);

  static unsigned long prevMicros = 0;
  static boolean lastState = LOW;

  if(lastState == LOW && currentState == HIGH){      // Rising edge
    prevMicros = currentMicros;
    lastState = currentState;
  }
  else if(lastState == HIGH && currentState == LOW){ // Falling edge
    pulseWidth = currentMicros - prevMicros;
    lastState = currentState;
  }

}
// Uses a pin change interrupt and micros() to get the pulsewidth at pin 4
void getPulsewidth2(){
  unsigned long currentMicros2 = micros();
  boolean currentState2 = digitalRead(4);

  static unsigned long prevMicros2 = 0;
  static boolean lastState2 = LOW;

  if(lastState2 == LOW && currentState2 == HIGH){      // Rising edge
    prevMicros2 = currentMicros2;
    lastState2 = currentState2;
  }
  else if(lastState2 == HIGH && currentState2 == LOW){ // Falling edge
    pulseWidth2 = currentMicros2 - prevMicros2;
    lastState2 = currentState2;
  }

}




// This is the main playback interrupt, keep this nice and tight!!
ISR(TIMER1_COMPA_vect) {
  OCR1A = currentSmpleRate;

  if (curEngineSample >= idle_len) { // Loop the sample
    curEngineSample = 0;
  }

  if (engineOn) {
    OCR2B = pgm_read_byte(&idle_data[curEngineSample]); // Volume
    curEngineSample++;
  }
  else OCR2B = 255; // Stop engine (volume = 0)

}

I forgot to mention Pin 2 goes to throttle and 4 to auxilary "start engine button". Everything works ok until im not trying attach interrupt for pin 4. Then no sound and no readings on both pins.

An Uno only allows interrupts on pins 2 and 3, not pin 4.

Also, your writePot() function does nothing, but the comments seem to indicate it is a volume control.

Ok thanks my bad i really forgot :confused: Again thanks!