Control two parameters via Serial communication

Control two parameters via Serial communication

Postby terr » Sun Dec 08, 2013 6:15 pm

Hi all.

I was wondering would it be possible to control the two parameters (potentiometers) : frequency and amplitude of the sin wave generator (or any two parameters from ) simultaneously via serial communication. I was hoping to try something the same as this post
http://forums.openmusiclabs.com/viewtopic.php?f=21&t=301
but using both mod1_value and mod0_value.

I have a bit of code already to try and break up byte into to two 4 bits and so control the two parameters. I will then write some code in Processing to sent a byte of data something similar to this A127B127 where the int values are between 0 and 127.

I just don't know what changes are needed in the ISR function to allow me to change both parameters. Any help would be greatly appreciated. Thanks

Code: Select all
 /*
sine_generator.pde
 guest openmusiclabs 7.7.11
 this program creates a sinewave of variable frequency and
 amplitude, presented at both left and right outputs. there
 isnt any interpolation, so you only get 256 discrete frequencies
 across the span of 44Hz to 10kHz.
 */

// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 44 // 44.1kHz sample rate
#define ADCS 2 // use both ADCs

// include necessary libraries
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>

// create data variables for audio transfer
// even though there is no input needed, the codec requires stereo data
int left_in = 0; // in from codec (LINE_IN)
int right_in = 0;
int left_out = 0; // out to codec (HP_OUT)
int right_out = 0;

//strings to store the values of upper and lower end of the incoming string
String slider1;
String slider2;

//store characters of incoming string
String readString ;

// create variables for ADC results
// it only has positive values -> unsigned
unsigned int mod0_value = 0;
unsigned int mod1_value = 0;

// create sinewave lookup table
// PROGMEM stores the values in the program memory
// it is automatically included with AudioCodec.h
PROGMEM  prog_int16_t sinewave[]  = {
  // this file is stored in AudioCodec.h and is a 1024 value
  // sinewave lookup table of signed 16bit integers
  // you can replace it with your own waveform if you like
#include <sinetable.inc>
};
unsigned int location; // lookup table value location


void setup() {
  // call this last if you are setting up other things
  AudioCodec_init(); // setup codec and microcontroller registers
}

void loop() {
  while (1){ // reduces clock jitter

    while (Serial.available()) {

      if (Serial.available()>0) {
        char c = Serial.read();
        readString += c;
      }
    }

    if (readString.length() >0) {
      // get int values
      slider1 =   readString.substring(1,3);
      slider2 =   readString.substring(5,7);

      int n1=0;
      int n2=0;
     
      //convert String to int
      char firstSlider[3];
      slider1.toCharArray(firstSlider, sizeof(firstSlider));
      n1=atoi(firstSlider);
     
      //convert String to int
      char secondSlider[3];
      slider2.toCharArray(secondSlider, sizeof(secondSlider));
      n2=atoi(secondSlider);

      if(readString.charAt(0)=='A'){
       
        mod0_value=n1;
       
      }
      if(readString.charAt(4)=='B'){

       mod1_value=n2;
       
      }
    }
  }
}

// timer1 interrupt routine - all data processed here
ISR(TIMER1_COMPA_vect, ISR_NAKED) { // dont store any registers

  // &'s are necessary on data_in variables
  AudioCodec_data(&left_in, &right_in, left_out, right_out);

  // create some temporary variables
  // these tend to work faster than using the main data variables
  // as they arent fetched and stored all the time
  int temp1;
  int temp2;

  // create a variable frequency and amplitude sinewave
  // fetch a sample from the lookup table
  temp1 = pgm_read_word_near(sinewave + location);
  // step through table at rate determined by mod1
  // use upper byte of mod1 value to set the rate
  // and have an offset of 1 so there is always an increment.
  location += 1 + (mod1_value >> 8);
  // if weve gone over the table boundary -> loop back
  // around to the other side.
  location &= 0x03ff; // fast way of doing rollover for 2^n numbers
  // otherwise it would look like this:
  // if (location >= 1024) {
  // location -= 1024;
  // }

  // set amplitude with mod0
  // multiply our sinewave by the mod0 value
  MultiSU16X16toH16(temp2, temp1, mod0_value);
  // our sinewave is now in temp2
  left_out = temp2; // put sinusoid out on left channel
  right_out = -temp2; // put inverted version out on right chanel

  // get ADC values
  // & is required before adc variables
  AudioCodec_ADC(&mod0_value, &mod1_value);

  reti(); // dont forget to return from the interrupt
}
terr
 
Posts: 4
Joined: Sat Oct 26, 2013 4:10 pm

Re: Control two parameters via Serial communication

Postby guest » Sun Dec 08, 2013 6:45 pm

there are 2 ways of doing this. i will show the easier one first, and if that doesnt work, we can dig deeper. the main issue is that the all of the codecshield libraries are written as interrupt driven, and the serial libarary needs interrupts as well.

Code: Select all
void setup() {
  Serial.begin(9600); // initialize serial port
  // call this last if you are setting up other things
  AudioCodec_init(); // setup codec and microcontroller registers
}

void loop() {
  if (Serial.available()) {
   int input  = Serial.read();
   // collect and create your variable completely before doing this last step
   cli; // turn off interrupts before transferring the number
   mod1_value = input;
   sei; // turn interrupts back on
  }
}
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Control two parameters via Serial communication

Postby terr » Tue Dec 17, 2013 10:18 am

Hi I have tried the following code but can't get it to change to values for frequency and volume. I don't know if its where we have the cli() and sei() methods thats the problem or not. Or if its a case that the code works but the pots are overwriting the values that are passed to it The code has changed a bit but it is still breaking up a byte. Making the pots redundant would be OK as we just want to change the values via serial.
Code: Select all
/*
sine_generator.pde
 guest openmusiclabs 7.7.11
 this program creates a sinewave of variable frequency and
 amplitude, presented at both left and right outputs. there
 isnt any interpolation, so you only get 256 discrete frequencies
 across the span of 44Hz to 10kHz.
 */

// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 44 // 44.1kHz sample rate
#define ADCS 2 // use both ADCs

// include necessary libraries
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>

// create data variables for audio transfer
// even though there is no input needed, the codec requires stereo data
int left_in = 0; // in from codec (LINE_IN)
int right_in = 0;
int left_out = 0; // out to codec (HP_OUT)
int right_out = 0;

//char array
char command[4];
//byte to hold serial.read()
byte b;
int index=0;

// create variables for ADC results
// it only has positive values -> unsigned
unsigned int mod0_value = 0;
unsigned int mod1_value = 0;

// create sinewave lookup table
// PROGMEM stores the values in the program memory
// it is automatically included with AudioCodec.h
PROGMEM  prog_int16_t sinewave[]  = {
  // this file is stored in AudioCodec.h and is a 1024 value
  // sinewave lookup table of signed 16bit integers
  // you can replace it with your own waveform if you like
#include <sinetable.inc>
};
unsigned int location; // lookup table value location


void setup() {
  Serial.begin(9600);
  AudioCodec_init(); // setup codec and microcontroller registers
}

void loop() {
  while (1); // reduces clock jitter
  readCommand();
  setValues();
}
void readCommand(){
  while(Serial.available()>0){
    if(index<4){
      b=Serial.read();
      command[index]=b;
      index++;
    }
    else if(index>=4){
      Serial.println(command);
      index=0;
    }
  }
}
void setValues(){
  int k1=command[1] - '0';
  int k2=command[2] - '0';
  int k3=command[3] - '0';
  int k=(k1*100)+(k2*10)+k3;
  switch(command[0]){
  case 'X':
    cli();
    mod0_value = k;
    sei();
    break;
  case 'Y':
    cli();
    mod1_value = k;
    sei();
    break;
  }
}

// timer1 interrupt routine - all data processed here
ISR(TIMER1_COMPA_vect, ISR_NAKED) { // dont store any registers

  // &'s are necessary on data_in variables
  AudioCodec_data(&left_in, &right_in, left_out, right_out);

  // create some temporary variables
  // these tend to work faster than using the main data variables
  // as they arent fetched and stored all the time
  int temp1;
  int temp2;

  // create a variable frequency and amplitude sinewave
  // fetch a sample from the lookup table
  temp1 = pgm_read_word_near(sinewave + location);
  // step through table at rate determined by mod1
  // use upper byte of mod1 value to set the rate
  // and have an offset of 1 so there is always an increment.
  location += 1 + (mod1_value >> 8);
  // if weve gone over the table boundary -> loop back
  // around to the other side.
  location &= 0x03ff; // fast way of doing rollover for 2^n numbers
  // otherwise it would look like this:
  // if (location >= 1024) {
  // location -= 1024;
  // }

  // set amplitude with mod0
  // multiply our sinewave by the mod0 value
  MultiSU16X16toH16(temp2, temp1, mod0_value);
  // our sinewave is now in temp2
  left_out = temp2; // put sinusoid out on left channel
  right_out = -temp2; // put inverted version out on right chanel

  // get ADC values
  // & is required before adc variables
  AudioCodec_ADC(&mod0_value, &mod1_value);

  reti(); // dont forget to return from the interrupt
}
terr
 
Posts: 4
Joined: Sat Oct 26, 2013 4:10 pm

Re: Control two parameters via Serial communication

Postby guest » Tue Dec 17, 2013 11:45 am

yes, the adc is overwriting the values. comment out that line, and set ADCS 0 at the beginning.

it will be difficult to use both the serial line and the adc to set the same value. you might be able to do something that looks for changes on the ADC, and only then does the ADC change the value. basically, store the last value, and compare it to the current value, and if the difference is greater than 10 or so, then change. there will be some noise on the ADC, so even if the knob isnt moving, the value will change a bit.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm


Return to Audio Codec Shield

Who is online

Users browsing this forum: No registered users and 1 guest


cron