I use a Teensy 4.0 with Audio Shield and try to control the Audio Shield via Bluetooth (DM10) and MIT app inventor.
All buttons / switches work well but with the slider / potentiometer I have problems.
I send via BLE values between 0-1023 to an analog input (analogWrite / analogRead) -> analogWrite(PinX, value) and after a short delay I try to read this PinX via analogRead(PinX) to adjust the volume.
Where is my error?
sketch -> see below
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
#define HWSERIAL Serial1 // Teensy 4.0 RX1 PIN0 / TX1 PIN1
AudioInputI2S i2s1; //xy=359,315
AudioFilterStateVariable filter1; //xy=446,176
AudioFilterStateVariable filter2; //xy=446,310
AudioMixer4 mixer1; // mixers to combine wav file and audio shield inputs
AudioMixer4 mixer2;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S audioOutput;
//AudioOutputSPDIF audioOutput;
//AudioOutputAnalog audioOutput;
// wire up the interfaces between audio components with patch cords
// mixer inputs
AudioConnection patchCord1(i2s1, 0, filter1, 0); // left channels into mixer 1
AudioConnection patchCord3(filter1, 0, mixer1, 0);
AudioConnection patchCord4(filter1, 1, mixer1, 1);
AudioConnection patchCord5(filter1, 2, mixer1, 2);
AudioConnection patchCord2(i2s1, 1, filter2, 0);
AudioConnection patchCord6(filter2, 0, mixer2, 0);
AudioConnection patchCord7(filter2, 1, mixer2, 1);
AudioConnection patchCord8(filter2, 2, mixer2, 2);
// mixer outputs
AudioConnection patchCord9(mixer1, 0, audioOutput, 0);
AudioConnection patchCord10(mixer2, 0, audioOutput, 1);
// object to allow control of the SGTL5000 audio shield settings
AudioControlSGTL5000 sgtl5000_1;
// Variables used for incoming data
const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;
// Constants for hardware / buttons and potentiometers
const byte SWITCH_PIN[] = {2,3,4}; // 2 = bass, 3 = band, 4 = high
const int SV = 18; // Volume
const int SF = 19; // Frequence
// audio shield volume
int masterVolume = 0;
void setup() {
for (byte pin = 0; pin < 3; pin++)
{
// Set the SWITCH pins for output and make them LOW
pinMode(SWITCH_PIN[pin], INPUT_PULLUP);
digitalWrite(SWITCH_PIN[pin],LOW);
}
pinMode(SV, INPUT_PULLUP);
digitalWrite(SV,LOW);
pinMode(SF, INPUT_PULLUP);
digitalWrite(SF,LOW);
Serial.begin(115200);
Serial.println(" ");
// open software serial connection to the Bluetooth module.
HWSERIAL.begin(115200);
Serial.println("HWSERIAL HM-10 started at 115200");
newData = false;
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(20);
// comment these out if not using the audio adaptor board.
Serial.print("init audio shield...");
sgtl5000_1.enable();
// audioShield.inputSelect(inputChSelect); // select mic or line-in for audio shield input source
sgtl5000_1.volume(0.5);
Serial.println("done.");
mixer1.gain(0, 0.0);
mixer1.gain(1, 1.0); // default to hearing band-pass signal
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.0);
mixer2.gain(0, 0.0);
mixer2.gain(1, 1.0);
mixer2.gain(2, 0.0);
mixer2.gain(3, 0.0);
delay(1000);
}
void loop()
{
recvWithStartEndMarkers(); // check to see if we have received any new commands
if (newData) { processCommand(); } // if we have a new command do something about it
}
/*
****************************************
* Function processCommand
* parses data commands contained in receivedChars[]
* receivedChars[] has not been checked for errors
*
* passed:
*
* global:
* receivedChars[]
* newData
*
* Returns:
*
* Sets:
* receivedChars[]
* newData
*/
void processCommand(){
Serial.print("receivedChars = "); Serial.println(receivedChars);
if (receivedChars[0] == 'S') // do we have a SWITCH command?
{
// we know the SWITCH command has a fixed length "S00"
// and the value at pos 1 is the SWITCH and the value at pos 2 is 0 or 1 (on/off).
// 0 and 1 is the same as LOW and HIGH so we can use 0/1 instead of LOW/HIGH
byte SWITCHnum = receivedChars[1] - 48; // convert ascii to value by subtracting 48
boolean SWITCHstatus = receivedChars[2] - 48;
Serial.print(SWITCHnum);
Serial.println(SWITCHstatus);
if (SWITCHnum == 0 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[0],HIGH);
Serial.println("Low Pass Signal");
mixer1.gain(0, 1.0); // hear low-pass signal
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.0);
mixer2.gain(0, 1.0);
mixer2.gain(1, 0.0);
mixer2.gain(2, 0.0);
}
if (SWITCHnum == 1 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[1],HIGH);
Serial.println("Band Pass Signal");
mixer1.gain(0, 0.0);
mixer1.gain(1, 1.0); // hear band-pass signal
mixer1.gain(2, 0.0);
mixer2.gain(0, 0.0);
mixer2.gain(1, 1.0);
mixer2.gain(2, 0.0);
}
if (SWITCHnum == 2 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[2],HIGH);
Serial.println("High Pass Signal");
mixer1.gain(0, 0.0);
mixer1.gain(1, 0.0);
mixer1.gain(2, 1.0); // hear high-pass signal
mixer2.gain(0, 0.0);
mixer2.gain(1, 0.0);
mixer2.gain(2, 1.0);
}
if (SWITCHnum == 0 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[1],LOW);
Serial.println("Low Pass Signal");
}
if (SWITCHnum == 1 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[0],LOW);
Serial.println("Band Pass Signal");
}
if (SWITCHnum == 2 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[2],LOW);
Serial.println("High Pass Signal");
}
}
if (receivedChars[0] == 'V') // do we have a slider command?
{
byte thousands = (receivedChars[1]-48) * 1000;
byte hundreds = (receivedChars[2]-48) * 100;
byte tens = (receivedChars[3]-48) * 10;
byte units = receivedChars[4]-48;
byte value = thousands + hundreds + tens + units;
Serial.print("Volume = ");
Serial.println(value);
// read volume control SLIDER SV and set audio shield volume if required
analogWrite(SV, value);
delay(500);
int vol = analogRead(SV);
if (vol != masterVolume) {
masterVolume = vol;
sgtl5000_1.volume((float)vol / 1023); // audio shield headphone out volume (optional)- original 1023
mixer1.gain(0, (float)vol / 1023); // software mixer input channel volume
mixer1.gain(1, (float)vol / 1023);
mixer2.gain(0, (float)vol / 1023);
mixer2.gain(1, (float)vol / 1023);
}
}
if (receivedChars[0] == 'F') // do we have a slider command?
{
byte thousands = (receivedChars[1]-48) * 1000;
byte hundreds = (receivedChars[2]-48) * 100;
byte tens = (receivedChars[3]-48) * 10;
byte units = receivedChars[4]-48;
byte value = thousands + hundreds + tens + units;
analogWrite(SF, value);
delay(500);
int knob = analogRead(SF);
float freq = expf((float)knob / 150.0) * 10.0 + 80.0; // original 150.0) * 10.0 + 80.0;
filter1.frequency(freq);
filter2.frequency(freq);
Serial.print("frequency = ");
Serial.println(freq);
delay(200);
}
receivedChars[0] = '\0';
newData = false;
}
// function recvWithStartEndMarkers by Robin2 of the Arduino forums
// See http://forum.arduino.cc/index.php?topic=288234.0
/*
****************************************
* Function recvWithStartEndMarkers
* reads serial data and returns the content between a start marker and an end marker.
*
* passed:
*
* global:
* receivedChars[]
* newData
*
* Returns:
*
* Sets:
* newData
* receivedChars
*
*/
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '[';
char endMarker = ']';
char rc;
if (HWSERIAL.available() > 0)
{
rc = HWSERIAL.read();
if (recvInProgress == true)
{
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx > maxDataLength) { ndx = maxDataLength; }
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) { recvInProgress = true; }
}
}
All buttons / switches work well but with the slider / potentiometer I have problems.
I send via BLE values between 0-1023 to an analog input (analogWrite / analogRead) -> analogWrite(PinX, value) and after a short delay I try to read this PinX via analogRead(PinX) to adjust the volume.
Where is my error?
sketch -> see below
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
#define HWSERIAL Serial1 // Teensy 4.0 RX1 PIN0 / TX1 PIN1
AudioInputI2S i2s1; //xy=359,315
AudioFilterStateVariable filter1; //xy=446,176
AudioFilterStateVariable filter2; //xy=446,310
AudioMixer4 mixer1; // mixers to combine wav file and audio shield inputs
AudioMixer4 mixer2;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S audioOutput;
//AudioOutputSPDIF audioOutput;
//AudioOutputAnalog audioOutput;
// wire up the interfaces between audio components with patch cords
// mixer inputs
AudioConnection patchCord1(i2s1, 0, filter1, 0); // left channels into mixer 1
AudioConnection patchCord3(filter1, 0, mixer1, 0);
AudioConnection patchCord4(filter1, 1, mixer1, 1);
AudioConnection patchCord5(filter1, 2, mixer1, 2);
AudioConnection patchCord2(i2s1, 1, filter2, 0);
AudioConnection patchCord6(filter2, 0, mixer2, 0);
AudioConnection patchCord7(filter2, 1, mixer2, 1);
AudioConnection patchCord8(filter2, 2, mixer2, 2);
// mixer outputs
AudioConnection patchCord9(mixer1, 0, audioOutput, 0);
AudioConnection patchCord10(mixer2, 0, audioOutput, 1);
// object to allow control of the SGTL5000 audio shield settings
AudioControlSGTL5000 sgtl5000_1;
// Variables used for incoming data
const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;
// Constants for hardware / buttons and potentiometers
const byte SWITCH_PIN[] = {2,3,4}; // 2 = bass, 3 = band, 4 = high
const int SV = 18; // Volume
const int SF = 19; // Frequence
// audio shield volume
int masterVolume = 0;
void setup() {
for (byte pin = 0; pin < 3; pin++)
{
// Set the SWITCH pins for output and make them LOW
pinMode(SWITCH_PIN[pin], INPUT_PULLUP);
digitalWrite(SWITCH_PIN[pin],LOW);
}
pinMode(SV, INPUT_PULLUP);
digitalWrite(SV,LOW);
pinMode(SF, INPUT_PULLUP);
digitalWrite(SF,LOW);
Serial.begin(115200);
Serial.println(" ");
// open software serial connection to the Bluetooth module.
HWSERIAL.begin(115200);
Serial.println("HWSERIAL HM-10 started at 115200");
newData = false;
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(20);
// comment these out if not using the audio adaptor board.
Serial.print("init audio shield...");
sgtl5000_1.enable();
// audioShield.inputSelect(inputChSelect); // select mic or line-in for audio shield input source
sgtl5000_1.volume(0.5);
Serial.println("done.");
mixer1.gain(0, 0.0);
mixer1.gain(1, 1.0); // default to hearing band-pass signal
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.0);
mixer2.gain(0, 0.0);
mixer2.gain(1, 1.0);
mixer2.gain(2, 0.0);
mixer2.gain(3, 0.0);
delay(1000);
}
void loop()
{
recvWithStartEndMarkers(); // check to see if we have received any new commands
if (newData) { processCommand(); } // if we have a new command do something about it
}
/*
****************************************
* Function processCommand
* parses data commands contained in receivedChars[]
* receivedChars[] has not been checked for errors
*
* passed:
*
* global:
* receivedChars[]
* newData
*
* Returns:
*
* Sets:
* receivedChars[]
* newData
*/
void processCommand(){
Serial.print("receivedChars = "); Serial.println(receivedChars);
if (receivedChars[0] == 'S') // do we have a SWITCH command?
{
// we know the SWITCH command has a fixed length "S00"
// and the value at pos 1 is the SWITCH and the value at pos 2 is 0 or 1 (on/off).
// 0 and 1 is the same as LOW and HIGH so we can use 0/1 instead of LOW/HIGH
byte SWITCHnum = receivedChars[1] - 48; // convert ascii to value by subtracting 48
boolean SWITCHstatus = receivedChars[2] - 48;
Serial.print(SWITCHnum);
Serial.println(SWITCHstatus);
if (SWITCHnum == 0 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[0],HIGH);
Serial.println("Low Pass Signal");
mixer1.gain(0, 1.0); // hear low-pass signal
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.0);
mixer2.gain(0, 1.0);
mixer2.gain(1, 0.0);
mixer2.gain(2, 0.0);
}
if (SWITCHnum == 1 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[1],HIGH);
Serial.println("Band Pass Signal");
mixer1.gain(0, 0.0);
mixer1.gain(1, 1.0); // hear band-pass signal
mixer1.gain(2, 0.0);
mixer2.gain(0, 0.0);
mixer2.gain(1, 1.0);
mixer2.gain(2, 0.0);
}
if (SWITCHnum == 2 && SWITCHstatus == 1) {
digitalWrite(SWITCH_PIN[2],HIGH);
Serial.println("High Pass Signal");
mixer1.gain(0, 0.0);
mixer1.gain(1, 0.0);
mixer1.gain(2, 1.0); // hear high-pass signal
mixer2.gain(0, 0.0);
mixer2.gain(1, 0.0);
mixer2.gain(2, 1.0);
}
if (SWITCHnum == 0 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[1],LOW);
Serial.println("Low Pass Signal");
}
if (SWITCHnum == 1 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[0],LOW);
Serial.println("Band Pass Signal");
}
if (SWITCHnum == 2 && SWITCHstatus == 0) {
digitalWrite(SWITCH_PIN[2],LOW);
Serial.println("High Pass Signal");
}
}
if (receivedChars[0] == 'V') // do we have a slider command?
{
byte thousands = (receivedChars[1]-48) * 1000;
byte hundreds = (receivedChars[2]-48) * 100;
byte tens = (receivedChars[3]-48) * 10;
byte units = receivedChars[4]-48;
byte value = thousands + hundreds + tens + units;
Serial.print("Volume = ");
Serial.println(value);
// read volume control SLIDER SV and set audio shield volume if required
analogWrite(SV, value);
delay(500);
int vol = analogRead(SV);
if (vol != masterVolume) {
masterVolume = vol;
sgtl5000_1.volume((float)vol / 1023); // audio shield headphone out volume (optional)- original 1023
mixer1.gain(0, (float)vol / 1023); // software mixer input channel volume
mixer1.gain(1, (float)vol / 1023);
mixer2.gain(0, (float)vol / 1023);
mixer2.gain(1, (float)vol / 1023);
}
}
if (receivedChars[0] == 'F') // do we have a slider command?
{
byte thousands = (receivedChars[1]-48) * 1000;
byte hundreds = (receivedChars[2]-48) * 100;
byte tens = (receivedChars[3]-48) * 10;
byte units = receivedChars[4]-48;
byte value = thousands + hundreds + tens + units;
analogWrite(SF, value);
delay(500);
int knob = analogRead(SF);
float freq = expf((float)knob / 150.0) * 10.0 + 80.0; // original 150.0) * 10.0 + 80.0;
filter1.frequency(freq);
filter2.frequency(freq);
Serial.print("frequency = ");
Serial.println(freq);
delay(200);
}
receivedChars[0] = '\0';
newData = false;
}
// function recvWithStartEndMarkers by Robin2 of the Arduino forums
// See http://forum.arduino.cc/index.php?topic=288234.0
/*
****************************************
* Function recvWithStartEndMarkers
* reads serial data and returns the content between a start marker and an end marker.
*
* passed:
*
* global:
* receivedChars[]
* newData
*
* Returns:
*
* Sets:
* newData
* receivedChars
*
*/
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '[';
char endMarker = ']';
char rc;
if (HWSERIAL.available() > 0)
{
rc = HWSERIAL.read();
if (recvInProgress == true)
{
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx > maxDataLength) { ndx = maxDataLength; }
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) { recvInProgress = true; }
}
}